Android自定义View: 组合按钮

       如上图,将两个按钮组合在一起,点击红色按钮将蓝色按钮隐藏或展开,中间用动画实现过渡,蓝色按钮上移或下移,红色按钮以一定规律旋转。实现思路不难,主要是熟悉一下自定义View的流程。

      1.自定义属性。在values目录下新建文件,设置自定义View的属性。本例我们设置两个按钮的半径j就行了。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="comboButton">
        <attr name="button_radius" format="dimension"/>
    </declare-styleable>
</resources>

       2.布局文件。从图可知这是组合控件,我们可以在LinearLayout中先放置按钮。

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:id="@+id/linear_layout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_change_bt"
        android:layout_margin="8dp"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/icon2"
        app:backgroundTint="#4f98e7"
        app:backgroundTintMode="src_in"/>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/floating_bt"
        android:layout_margin="8dp"
        android:layout_marginTop="10dp"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:backgroundTint="#dc5d48"
        android:src="@mipmap/icon"
       />
</LinearLayout>

       3.编写自定义View。新建comboButton类继承LinearLayout,注意类名要与自定义属性文件中declare-styleable的name相同,才能获取到自定义属性。

public class comboButton extends LinearLayout implements View.OnClickListener{
    private FloatingActionButton button;   //红色按钮
    private FloatingActionButton changeButton; //蓝色按钮
    private float buttonY; //红色按钮Y坐标
    private float changeButtonY; //蓝色按钮Y坐标
    private click mClick; // 点击实例
    private int radius; //半径

    public comboButton(Context context){
        this(context,null,0);
    }

    public comboButton(Context context, AttributeSet attrs){
        this(context, attrs,0);
    }

    public comboButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //获取自定义属性
        TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.comboButton,defStyleAttr,0);
        radius = array.getInteger(R.styleable.comboButton_button_radius,100);
        array.recycle();
        initView(context);
    }

    public void initView(Context context){
        //引入布局
        LayoutInflater.from(context).inflate(R.layout.combo_button, this, true);
        button = findViewById(R.id.floating_bt);
        changeButton = findViewById(R.id.floating_change_bt);
        //设置半径
        android.view.ViewGroup.LayoutParams lp = button.getLayoutParams();
        lp.width = radius;
        lp.height = radius;
        lp = changeButton.getLayoutParams();
        lp.width = radius;
        lp.height = radius;
        //设置点击
        button.setOnClickListener(this);
        changeButton.setOnClickListener(this);
        //先将蓝色按钮设为不可见,不可点击
        if(changeButton.getVisibility() == VISIBLE){
            changeButton.setVisibility(INVISIBLE);
            changeButton.setEnabled(false);
        }
        //获取两个按钮Y坐标,将蓝色按钮坐标改为红色坐标,达到与红色重叠效果
        new Thread(){
            @Override
            public void run() {
                try {
                    sleep(300);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                buttonY = button.getY();
                changeButtonY = changeButton.getY();
                changeButton.setY(buttonY);
            }
        }.start();
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.floating_bt:
                //根据蓝色按钮状态响应点击事件
                if(changeButton.getVisibility() == INVISIBLE){
                    //将蓝色变为可见,可点击
                    changeButton.setVisibility(VISIBLE);
                    changeButton.setEnabled(true);
                    //设置动画效果
                    ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(changeButton,"translationY", 0 );
                    ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button,"rotation",0f, 45f);
                    AnimatorSet set = new AnimatorSet();
                    set.setDuration(1000);
                    set.play(objectAnimator).with(objectAnimator1);
                    set.start();
                }else if(changeButton.getVisibility() == VISIBLE){
                    //设置动画效果
                    ObjectAnimator objectAnimator =ObjectAnimator.ofFloat(changeButton,"translationY",buttonY - changeButtonY);
                    ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button,"rotation",45f, 0f);
                    AnimatorSet set = new AnimatorSet();
                    set.setDuration(1000);
                    set.play(objectAnimator).with(objectAnimator1);
                    set.start();
                    //动画结束将蓝色按钮设为不可见,不可点击
                    set.addListener(new AnimatorListenerAdapter() {

                        @Override
                        public void onAnimationEnd(Animator animation) {
                            changeButton.setVisibility(INVISIBLE);
                            changeButton.setEnabled(false);
                        }
                    });

                }
                break;
            case R.id.floating_change_bt:
                //蓝色按钮点击事件设置接口,外部调用
                mClick.onButtonClick();
        }
    }
    
    public void setClickEvent(click c){
        mClick = c;
    }
    //蓝色按钮点击接口
    interface click{
        void onButtonClick();
    }
}

       由布局文件可知蓝色按钮一开始在红色上面,即展开状态。所以在初始化时我们先将蓝色按钮设为不可见,并将Y坐标设为与红色按钮相同,达到重叠效果(这里先将两个按钮Y坐标保存,以后还需要用到)。从上面代码可以看到我们先开个线程sleep一小段时间后才获取按钮的坐标。这是因为一开始就获取的话获取到的值为0.0。(可通过打印日志证明)。

       当点击红色按钮时,根据蓝色按钮是否可见,即是否展开响应事件。展开收起通过设置属性动画实现过渡。蓝色按钮的点击事件具体逻辑通过设置接口回调,交给外部设置。

       接着只要在布局中引用就可以了。(当然这个控件并不是那么完美)

猜你喜欢

转载自blog.csdn.net/Yang_RT/article/details/82928969