可拖拽懸浮球,仿Assistive Touch彈出窗口


效果實現圖:
在這裏插入圖片描述

懸浮球

android自帶的FloatingActionButton沒有拖拽功能,因此可以給它加上這個功能。
直接上代碼:

public class DragFloatActionButton extends FloatingActionButton{

    private int parentHeight;
    private int parentWidth;

    public DragFloatActionButton(Context context) {
        super(context);
    }

    public DragFloatActionButton(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public DragFloatActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }


    private int lastX;
    private int lastY;

    private boolean isDrag;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                setPressed(true);
                isDrag=false;
                getParent().requestDisallowInterceptTouchEvent(true);
                lastX=rawX;
                lastY=rawY;
                ViewGroup parent;
                if(getParent()!=null){
                    parent= (ViewGroup) getParent();
                    parentHeight=parent.getHeight();
                    parentWidth=parent.getWidth();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if(parentHeight<=0||parentWidth==0){
                    isDrag=false;
                    break;
                }else {
                    isDrag=true;
                }
                int dx=rawX-lastX;
                int dy=rawY-lastY;
                //這裏修復一些華爲手機無法觸發點擊事件
                int distance= (int) Math.sqrt(dx*dx+dy*dy);
                if(distance==0){
                    isDrag=false;
                    break;
                }
                float x=getX()+dx;
                float y=getY()+dy;
                //檢測是否到達邊緣 左上右下
                x=x<0?0:x>parentWidth-getWidth()?parentWidth-getWidth():x;
                y=getY()<0?0:getY()+getHeight()>parentHeight?parentHeight-getHeight():y;
                setX(x);
                setY(y);
                lastX=rawX;
                lastY=rawY;
                Log.i("aa","isDrag="+isDrag+"getX="+getX()+";getY="+getY()+";parentWidth="+parentWidth);
                break;
            case MotionEvent.ACTION_UP:
                if(!isNotDrag()){
                    //恢復按壓效果
                    setPressed(false);
                    //Log.i("getX="+getX()+";screenWidthHalf="+screenWidthHalf);
                    if(rawX>=parentWidth/2){
                        //靠右吸附
                        animate().setInterpolator(new DecelerateInterpolator())
                                .setDuration(500)
                                .xBy(parentWidth-getWidth()-getX())
                                .start();
                    }else {
                        //靠左吸附
                        ObjectAnimator oa=ObjectAnimator.ofFloat(this,"x",getX(),0);
                        oa.setInterpolator(new DecelerateInterpolator());
                        oa.setDuration(500);
                        oa.start();
                    }
                }
                break;
        }
        //如果是拖拽則消s耗事件,否則正常傳遞即可。
        return !isNotDrag() || super.onTouchEvent(event);
    }

    private boolean isNotDrag(){
        return !isDrag&&(getX()==0
                ||(getX()==parentWidth-getWidth()));
    }
}

layout中使用DragFloatActionButton

<DragFloatActionButton
        android:id="@+id/floatBall"  
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:backgroundTint="@drawable/fab"          --->正常背景顏色,默認使用colorAccent的顏色
        app:rippleColor="#ffffff"                   --->按下時背景顏色
        app:elevation="6dp"                         --->正常陰影大小
        app:pressedTranslationZ="12dp"              --->按下時陰影大小
        app:borderWidth="0dp"                       --->邊框大小
        app:fabCustomSize="60dp"                    --->fab大小
        app:maxImageSize="50dp"                     --->src圖片的大小
        android:src="@drawable/circle"
        android:clickable="true"                    --->點擊效果
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

最重要的事情!!!一定要給DragFloatActionButton設置點擊事件,否則不能拖拽!

完整代碼:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    //懸浮球
    private DragFloatActionButton floatBall;
    //彈窗
    private PopupWindow popup;
    //彈窗菜單View
    private View menuView;
    //菜單上面的組件
    private TextView menuTime;
    private TextView menuPhone;
    private TextView menuAirCondition;
    private TextView menuLight;
    private TextView menuAir;
    private TextView menuITPower;
    private TextView menuMusic;
    private TextView menuLog;
    private TextView menuSetting;
    private TextView menuMain;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    //初始化view
    private void initView() {
        floatBall = findViewById(R.id.floatBall);
        menuView = LayoutInflater.from(this).inflate(R.layout.float_menu, null);
        menuTime = menuView.findViewById(R.id.menu_time);
        menuPhone = menuView.findViewById(R.id.menu_phone);
        menuAirCondition = menuView.findViewById(R.id.menu_airCondition);
        menuLight = menuView.findViewById(R.id.menu_lighting);
        menuAir = menuView.findViewById(R.id.menu_air);
        menuITPower = menuView.findViewById(R.id.menu_power);
        menuMusic = menuView.findViewById(R.id.menu_music);
        menuLog = menuView.findViewById(R.id.menu_log);
        menuSetting = menuView.findViewById(R.id.menu_setting);
        menuMain = menuView.findViewById(R.id.menu_main);

        menuTime.setOnClickListener(this);
        menuPhone.setOnClickListener(this);
        menuAirCondition.setOnClickListener(this);
        menuLight.setOnClickListener(this);
        menuAir.setOnClickListener(this);
        menuITPower.setOnClickListener(this);
        menuMusic.setOnClickListener(this);
        menuLog.setOnClickListener(this);
        menuSetting.setOnClickListener(this);
        menuMain.setOnClickListener(this);
        floatBall.setOnClickListener(this);
    }

    //顯示View
    private void showView() {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        popup = new PopupWindow(menuView, (int) (dm.widthPixels * 0.7), (int) (dm.heightPixels * 0.5));
        Drawable transpent = new ColorDrawable(Color.TRANSPARENT);
        popup.setBackgroundDrawable(transpent);
        popup.setFocusable(true);
        popup.setOutsideTouchable(true);
        popup.showAtLocation(floatBall, Gravity.CENTER, 0, 0);
        popup.update();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.floatBall:
                showView();
                break;

            default: break;
        }
    }

}

浮動菜單窗口透明化

android:alpha="0.8"

源代碼

GitHub傳送門

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