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。(可通過打印日誌證明)。

       當點擊紅色按鈕時,根據藍色按鈕是否可見,即是否展開響應事件。展開收起通過設置屬性動畫實現過渡。藍色按鈕的點擊事件具體邏輯通過設置接口回調,交給外部設置。

       接着只要在佈局中引用就可以了。(當然這個控件並不是那麼完美)

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章