可拖拽懸浮球,仿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"