Android Design Support Library里面汇集了很多重要的 material design 控件,支持所有 Android 2.1 及后续版本。里面你可以看到 navigation drawer view、floating labels、floating action button、snackbar、tabs,以及一套将它们紧密结合在一起的动作与滚动框架。
在刷新了整个 Android 的用户体验的同时,但要设计出完全符合 material design 哲学的应用,也是一个很大的挑战。
基于FloatingActionButton我设计了一个可拖拽动态弹出效果的功能菜单,其效果如下图所示
第0步:在Android Studio中build.gradle添加依赖:
compile 'com.android.support:design:23.4.0' compile 'com.jakewharton:butterknife:7.0.1'
第一步:创建可拖拽的FloatingDraftButton 继承FloatingActionButton 实现OnTouchListener方法
import android.content.Context; import android.support.design.widget.FloatingActionButton; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import com.cpcn.demo.util.ScreenUtil; import java.util.ArrayList; public class FloatingDraftButton extends FloatingActionButton implements View.OnTouchListener{ int lastX, lastY; int originX, originY; final int screenWidth ; final int screenHeight ; private ArrayList<FloatingActionButton> floatingActionButtons = new ArrayList<FloatingActionButton>(); public FloatingDraftButton(Context context) { this(context, null); } public FloatingDraftButton(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FloatingDraftButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); screenWidth = ScreenUtil.getScreenWidth(context); screenHeight = ScreenUtil.getContentHeight(context); setOnTouchListener(this); }
//注册归属的FloatingActionButton public void registerButton(FloatingActionButton floatingActionButton){ floatingActionButtons.add(floatingActionButton); } public ArrayList<FloatingActionButton> getButtons(){ return floatingActionButtons; } public int getButtonSize(){ return floatingActionButtons.size(); } //是否可拖拽 一旦展开则不允许拖拽 public boolean isDraftable(){ for(FloatingActionButton btn:floatingActionButtons){ if(btn.getVisibility() == View.VISIBLE ){ return false; } } return true; }
//当被拖拽后其所属的FloatingActionButton 也要改变位置 private void slideButton(int l, int t, int r, int b){ for(FloatingActionButton floatingActionButton:floatingActionButtons){ floatingActionButton.layout(l, t, r, b); } } @Override public boolean onTouch(View v, MotionEvent event) { if(!isDraftable()){ return false; } int ea = event.getAction(); switch (ea) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getRawX();// 获取触摸事件触摸位置的原始X坐标 lastY = (int) event.getRawY(); originX = lastX; originY = lastY; break; case MotionEvent.ACTION_MOVE: int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int l = v.getLeft() + dx; int b = v.getBottom() + dy; int r = v.getRight() + dx; int t = v.getTop() + dy; // 下面判断移动是否超出屏幕 if (l < 0) { l = 0; r = l + v.getWidth(); } if (t < 0) { t = 0; b = t + v.getHeight(); } if (r > screenWidth) { r = screenWidth; l = r - v.getWidth(); } if (b > screenHeight) { b = screenHeight; t = b - v.getHeight(); } v.layout(l, t, r, b); slideButton(l,t,r,b); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); v.postInvalidate(); break; case MotionEvent.ACTION_UP: int distance = (int) event.getRawX() - originX + (int)event.getRawY() - originY; Log.e("DIstance",distance+""); if (Math.abs(distance)<20) { //当变化太小的时候什么都不做 OnClick执行 }else { return true; } break; } return false; } }
第二步:创建布局layout_floatingmenu.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.cpcn.demo.widget.Button.FloatingDraftButton