商城首页欢迎来到中国正版软件门户

您的位置:首页 >2.3.3 Button(按钮)与ImageButton(图像按钮)

2.3.3 Button(按钮)与ImageButton(图像按钮)

  发布于2026-08-12 阅读(0)

扫一扫,手机访问

本节引言:

这一段来聊 Android 基本控件里的两种按钮:Button 普通按钮和 ImageButton 图像按钮。ImageButton 的用法其实和 Button 大体一致;至于和图片显示相关的部分,后面讲到 ImageView 时也会覆盖到,所以这一节把重点放在 Button 上就够了。还有一点别忽略,Button 本质上是 TextView 的子类,因此 TextView 上不少属性,同样可以直接用在 Button 上。回到实际开发,Button 最常见的处理,无非就是围绕几种状态做样式切换:按下时一个颜色,抬起后另一个颜色,禁用时再显示另一种颜色。说白了,这类效果通常就是借助 StateListDrawable 这种 Drawable 资源来完成,也就是单独写一个 drawable 资源文件。铺垫先到这里,下面直接进入本节内容。

1.StateListDrawable简介:

StateListDrawable是Drawable资源的一种,可以根据不同的状态,设置不同的图片效果,关键节点 < selector >,我们只需要将Button的background属性设置为该drawable资源即可轻松实现,按下 按钮时不同的按钮颜色或背景!

我们可以设置的属性:

  • drawable:引用的Drawable位图,我们可以把他放到最前面,就表示组件的正常状态~
  • state_focused:是否获得焦点
  • state_window_focused:是否获得窗口焦点
  • state_enabled:控件是否可用
  • state_checkable:控件可否被勾选,eg:checkbox
  • state_checked:控件是否被勾选
  • state_selected:控件是否被选择,针对有滚轮的情况
  • state_pressed:控件是否被按下
  • state_active:控件是否处于活动状态,eg:slidingTab
  • state_single:控件包含多个子控件时,确定是否只显示一个子控件
  • state_first:控件包含多个子控件时,确定第一个子控件是否处于显示状态
  • state_middle:控件包含多个子控件时,确定中间一个子控件是否处于显示状态
  • state_last:控件包含多个子控件时,确定最后一个子控件是否处于显示状态

2.实现按钮的按下效果:

好的,先准备三个图片背景,一般我们为了避免按钮拉伸变形都会使用.9.png作为按钮的drawable! 先来看下 运行效果图:

代码实现:



    
    
    

布局文件:activity_main.xml

MainActivity.ja va

public class MainActivity extends Activity {
private Button btnOne,btnTwo;
@Override
    protected void onCreate(Bundle sa vedInstanceState) {
        super.onCreate(sa vedInstanceState);
        setContentView(R.layout.activity_main);
        btnOne = (Button) findViewById(R.id.btnOne);
        btnTwo = (Button) findViewById(R.id.btnTwo);
        btnTwo.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if(btnTwo.getText().toString().equals("按钮不可用")){
                    btnOne.setEnabled(false);
                    btnTwo.setText("按钮可用");
                }else{
                    btnOne.setEnabled(true);
                    btnTwo.setText("按钮不可用");
                }
            }
        });
    }
}

3.使用颜色值绘制圆角按钮

很多时候,手头未必有美工支持;要么不会用PS、秀图工具之类的软件,要么就是单纯不想自己折腾做图。其实这种场景下,完全可以直接用代码把按钮背景写出来,颜色想怎么配就怎么配。下面就来做一个带圆角的按钮背景。这里会用到另一个drawable资源:ShapeDrawable,先不展开细讲,后面会把每一种drawable单独说明清楚。眼下先会用就够了,本质上也只是把EditText的Background属性改一下而已,这里就只贴drawable资源。

先看下效果图:

bbuton_danger_rounded.xml:




            
            
            
        

        
            
            
        

            
            
            
        

color.xml:



    #ffd2322d
    #ffd43f3a
    #a5d9534f
    #a5d43f3a
    #ffd9534f
    #FFFFFF

dimens.xml:

5dp

4.实现Material Design水波效果的Button

如果你的Android手机是5.0以上的系统,相信对下面这种按钮点击效果并不会陌生:

实现效果图:

快的那个是按下后的效果,慢的是长按后的效果!

实现逻辑:

1.我们继承ImageButton,当然你可以换成Button或者View,这里笔者想把龟放到中间才继承ImageButton

2.首先,创建两个Paint(画笔)对象,一个绘制底部背景颜色,一个绘制波纹扩散的

3.接着计算最大半径,开始半径每隔一段时间递增一次,直到等于最大半径,然后重置状态!

PS:大概的核心,刚学可能对自定义View感到陌生,没事,这里了解下即可,以后我们会讲,当然 你可以自己扣扣,注释还是蛮详细的~

实现代码:

自定义ImageButton:MyButton.ja va

package demo.com.jay.buttondemo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ImageButton;
/**
 * Created by coder-pig on 2015/7/16 0016.
 */
public class MyButton extends ImageButton {
private static final int INVALIDATE_DURATION = 15;     //每次刷新的时间间隔
    private static int DIFFUSE_GAP = 10;                  //扩散半径增量
    private static int TAP_TIMEOUT;                         //判断点击和长按的时间
private int viewWidth, viewHeight;                   //控件宽高
    private int pointX, pointY;                          //控件原点坐标(左上角)
    private int maxRadio;                             //扩散的最大半径
    private int shaderRadio;                        //扩散的半径
private Paint bottomPaint, colorPaint;          //画笔:背景和水波纹
    private boolean isPushButton;                 //记录是否按钮被按下
private int eventX, eventY;                  //触摸位置的X,Y坐标
    private long downTime = 0;                 //按下的时间
public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
        TAP_TIMEOUT = ViewConfiguration.getLongPressTimeout();
    }
/*
    * 初始化画笔
    * */
    private void initPaint() {
        colorPaint = new Paint();
        bottomPaint = new Paint();
        colorPaint.setColor(getResources().getColor(R.color.reveal_color));
        bottomPaint.setColor(getResources().getColor(R.color.bottom_color));
    }
@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (downTime == 0) downTime = SystemClock.elapsedRealtime();
                eventX = (int) event.getX();
                eventY = (int) event.getY();
                //计算最大半径:
                countMaxRadio();
                isPushButton = true;
                postInvalidateDelayed(INVALIDATE_DURATION);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if(SystemClock.elapsedRealtime() - downTime < TAP_TIMEOUT){
                    DIFFUSE_GAP = 30;
                    postInvalidate();
                }else{
                    clearData();
                }
                break;
        }
        return super.onTouchEvent(event);
    }
@Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if(!isPushButton) return; //如果按钮没有被按下则返回
        //绘制按下后的整个背景
        canvas.drawRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight, bottomPaint);
        canvas.sa ve();
        //绘制扩散圆形背景
        canvas.clipRect(pointX, pointY, pointX + viewWidth, pointY + viewHeight);
        canvas.drawCircle(eventX, eventY, shaderRadio, colorPaint);
        canvas.restore();
        //直到半径等于最大半径
        if(shaderRadio < maxRadio){
            postInvalidateDelayed(INVALIDATE_DURATION,
                    pointX, pointY, pointX + viewWidth, pointY + viewHeight);
            shaderRadio += DIFFUSE_GAP;
        }else{
            clearData();
        }
    }
/*
        * 计算最大半径的方法
        * */
    private void countMaxRadio() {
        if (viewWidth > viewHeight) {
            if (eventX < viewWidth / 2) {
                maxRadio = viewWidth - eventX;
            } else {
                maxRadio = viewWidth / 2 + eventX;
            }
        } else {
            if (eventY < viewHeight / 2) {
                maxRadio = viewHeight - eventY;
            } else {
                maxRadio = viewHeight / 2 + eventY;
            }
        }
    }
/*
    * 重置数据的方法
    * */
    private void clearData(){
        downTime = 0;
        DIFFUSE_GAP = 10;
        isPushButton = false;
        shaderRadio = 0;
        postInvalidate();
    }
@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.viewWidth = w;
        this.viewHeight = h;
    }
}

color.xml:



    #FFFFFF
    #3086E4
    #40BAF8

activity_main.xml:



源码下载(AS工程的哦):ButtonDemo.zip

本节小结:

本节给大家介绍了Button在实际开发中的一些用法,可能有些东西我们还没学,这里 知道下即可,后面学到自然会深入讲解,谢谢~

本文转载于:https://www.runoob.com/w3cnote/android-tutorial-button-imagebutton.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。
  • Ubuntu如何设置具体的系统崩溃自动回滚项 正版软件
    Ubuntu如何设置具体的系统崩溃自动回滚项
    Ubuntu没有内置崩溃自动回滚机制,所谓“自动”实为Timeshift定时快照+手动恢复、GRUB选旧内核或Btrfs快照重启切换;内核panic时调度已失效,无法安全执行快照操作,唯一可控动作是kernel.panic=10强制重启。Ubuntu 本身并没有内置“崩溃后自动回滚”这套机制——系统
    1小时前 10:11 0
  • Ubuntu如何设置具体的终端背景透明度 正版软件
    Ubuntu如何设置具体的终端背景透明度
    Ubuntu 里,终端透明度并不存在一条“通用命令”能一把梭解决,得先用 ps -o comm= -p $PPID 确认当前真正运行的是哪个终端程序,比如 ptyxis、gnome-terminal-server 等,再按对应方案分别处理:ptyxis 需要通过 dconf 写入对应的 UUID 路
    1小时前 10:11 0
  • CentOS 7怎么修改具体的磁盘分区UUID 正版软件
    CentOS 7怎么修改具体的磁盘分区UUID
    能修改的是ext2/ext3/ext4分区UUID,xfs不支持;必须先卸载分区,再用tune2fs -U random或指定值修改,之后同步更新fstab和GRUB配置,否则系统可能无法启动。修改 ext4/ext3 分区的 UUID 用 tune2fs只有 ext 系列(ext2/ext3/ex
    1小时前 10:10 0
  • Linux怎么查看逻辑卷扩容损坏日志 正版软件
    Linux怎么查看逻辑卷扩容损坏日志
    扩容一旦失败,排查通常先盯住三处日志:用dmesg看硬件层面有没有异常;用journalctl -u lvm2-monitor.service检查LVM服务监控状态;再用journalctl -b | grep -i "lvm|xfs|resize"把系统级提示捞出来。要是lvextend表面上没报
    1小时前 10:10 0
  • Linux怎么查看具体的父子进程树 正版软件
    Linux怎么查看具体的父子进程树
    pstree -p 是最准最快的方式,直接输出带PID的缩进树,括号内数字即真实PID,可直用于kill或strace;而ps -ef或ps --forest为扁平列表,父子关系需手动比对PPID,易跳层、漏看、断链。pstree -p 是最准、最快的方式,直接输出带 PID 的缩进树,括号里的数字
    1小时前 10:09 0