Android自定义一个有按下抬起效果ButtonView

先看效果

具备按下抬起效果的VIEW

如视频中,我们有很多按钮,这些按钮都用共同的属性,按下时亮起,抬起时恢复原背景,因此我们要自定义一个View,轻松实现这个功能,避免写太多重复代码。

一、自定义属性

在values文件夹中建一个attrs.xml文件,定义属性,如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <!--自定义属性-->
    <declare-styleable name="HHHH">
        <attr name="txt" format="string"/>
        <attr name="txt_size" format="dimension"/>
        <attr name="txt_color" format="reference|color"/>
        <attr name="down_img" format="reference"/>
        <attr name="up_img" format="reference"/>
    </declare-styleable>

</resources>
二、自定义ButtonView,并使用上面的属性

(1)在layout包下新建一个名为view_button的xml布局文件,代码如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/btn"
        android:gravity="center"
        android:textSize="@dimen/dp20"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

(2)实现逻辑

public class ButtonView extends LinearLayout {

    public ButtonViewK9(Context context) {
        this(context,null);
    }

    public ButtonViewK9(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    private View view;
    public ButtonViewK9(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        view = LayoutInflater.from(context).inflate(R.layout.view_button,this,true);

        //通过TypedArray获取相应的属性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.BridgeView);
        Drawable downImg = typedArray.getDrawable(R.styleable.HHHH_down_img);
        Drawable upImg = typedArray.getDrawable(R.styleable.HHHH_up_img);
        String text = typedArray.getString(R.styleable.HHHH_txt);
        int textColor=typedArray.getColor(R.styleable.HHHH_txt_color, Color.BLACK);
        float textSize = typedArray.getDimension(R.styleable.HHHH_txt_size,-1f);

        TextView textView=(TextView) view.findViewById(R.id.btn);
        textView.setBackground(upImg);
        textView.setText(text);
        //这个属性值可以不用设置
        if (textColor!=Color.BLACK)textView.setTextColor(textColor);
        //这个属性值可以不用设置
        if (textSize!=-1f)textView.setTextSize(textSize);
        //监听触摸事件
        textView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                float downX=0;
                float downY=0;
                if (motionEvent.getAction()==MotionEvent.ACTION_DOWN){
                    //设置按下显示的背景
                    textView.setBackground(downImg);
                    
                    //记录按下坐标点
                    downX=motionEvent.getX();
                    downY=motionEvent.getY();
                    return true;
                }

                if (motionEvent.getAction()==MotionEvent.ACTION_UP){
                    //设置抬起显示的背景
                    textView.setBackground(upImg);
                    
                    //手势拖到按下点以外100px的地方,视为放弃点击
                    if (Math.abs(motionEvent.getX()-downX)>100)return false;
                    if (Math.abs(motionEvent.getY()-downY)>100)return false;
                    
                    //把事件传递给点击事件接口,使用时我们就能直接使用OnClickListener获取点击事件
                    if (onClickListener!=null)onClickListener.onClick(ButtonView.this);
                    return true;
                }
                return false;
            }
        });
    }

    private OnClickListener onClickListener;
    @Override
    public void setOnClickListener(@Nullable OnClickListener onClickListener) {
        //拦截单击事件,使用时我们就能直接使用OnClickListener获取点击事件
        this.onClickListener=onClickListener;
    }
    
}
二、使用方法

(1)先准备两张背景图,这里我用xml的shape绘制背景, 在drawable包下新建名:down_back.xml 和 up_back.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!--<gradient
        android:startColor="#FFFFFF"
        android:endColor="#97B5C3"
        android:angle="50"/>-->
    <!--背景颜色渐变 angle为渐变角度-->

    <solid android:color="#FFC107" />
    <!-- 背景填充颜色 -->

    <stroke android:width="0dp" android:color="#252525" />
    <!--描边,边框宽度、颜色-->

    <corners android:radius="10dp" />
    <!-- 边角圆弧的半径 -->

    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
    <!-- 四周留出来的空白 -->

</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!--<gradient
        android:startColor="#FFFFFF"
        android:endColor="#97B5C3"
        android:angle="50"/>-->
    <!--背景颜色渐变 angle为渐变角度-->

    <solid android:color="#F4F4F4" />
    <!-- 背景填充颜色 -->

    <stroke android:width="0dp" android:color="#252525" />
    <!--描边,边框宽度、颜色-->

    <corners android:radius="10dp" />
    <!-- 边角圆弧的半径 -->

    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
    <!-- 四周留出来的空白 -->

</shape>

(2) 在最终使用的布局中引用上面两个背景

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:demo="http://schemas.android.com/apk/res-auto" (需要特别注意的是这一句,不能缺少)
    android:orientation="vertical"
    android:gravity="center"
    android:id="@+id/out_view"
    android:background="#77000000"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.包路径.ButtonView
        android:id="@+id/ok"
        android:layout_margin="@dimen/dp10"
        android:layout_width="@dimen/dp100"
        android:layout_height="@dimen/dp60"
        demo:down_img="@drawable/down_back"
        demo:up_img="@drawable/up_back"
        demo:txt="确定"
        demo:txt_size="20dp"
        demo:txt_color="#FFFFFF"/>

</LinearLayout>

到此,就实现了开头的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绝命三郎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值