悬浮按钮floatingActionbutton是AndroID 5.0系统添加的新控件,floatingActionbutton是继承至ImageVIEw,所以floatingActionbutton拥有ImageVIEw的所有属性。本文讲解的是一个实现了可拖拽的悬浮按钮,并为此添加了类似于qq的吸附边框的功能。在此之前,先了解下其简单的使用方式吧:
首先你得添加其依赖
compile 'com.androID.support:design:25.3.1'
然后在布局文件中使用。
<androID.support.design.Widget.floatingActionbutton androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="right|bottom" androID:src="@drawable/ic_launcher" />
如图:
floatingActionbutton正常显示的情况下有个填充的颜色,有个阴影;点击的时候会有一个ripplecolor,并且阴影的范围可以增大。其中:
1、填充的颜色默认使用就是style当中的colorAccent。
2、ripplecolor默认取的是theme当中的colorControlHighlight。
3、elevation和pressedTranslationZ,前者用户设置正常显示的阴影大小;后者是点击时显示的阴影大小。
好了,现在介绍本文的重点:可拖拽的,有吸附功能的悬浮按钮
先上代码。
import androID.animation.ObjectAnimator;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.animation.DecelerateInterpolator;public class DragfloatActionbutton extends floatingActionbutton { private int screenWIDth; private int screenHeight; private int screenWIDthHalf; private int statusHeight; private int virtualHeight; public DragfloatActionbutton(Context context) { super(context); init(); } public DragfloatActionbutton(Context context,AttributeSet attrs) { super(context,attrs); init(); } public DragfloatActionbutton(Context context,AttributeSet attrs,int defStyleAttr) { super(context,attrs,defStyleAttr); init(); } private voID init() { screenWIDth = ScreenUtils.getScreenWIDth(getContext()); screenWIDthHalf = screenWIDth / 2; screenHeight = ScreenUtils.getScreenHeight(getContext()); statusHeight = ScreenUtils.getStatusHeight(getContext()); virtualHeight=ScreenUtils.getVirtualbarHeigh(getContext()); } 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: isDrag = false; getParent().requestdisallowIntercepttouchEvent(true); lastX = rawX; lastY = rawY; Log.e("down---->","getX=" + getX() + ";screenWIDthHalf=" + screenWIDthHalf); break; case MotionEvent.ACTION_MOVE: isDrag = true; //计算手指移动了多少 int dx = rawX - lastX; int dy = rawY - lastY; //这里修复一些手机无法触发点击事件的问题 int distance= (int) Math.sqrt(dx*dx+dy*dy); Log.e("distance---->",distance+""); if(distance<3){//给个容错范围,不然有部分手机还是无法点击 isDrag=false; break; } float x = getX() + dx; float y = getY() + dy; //检测是否到达边缘 左上右下 x = x < 0 ? 0 : x > screenWIDth - getWIDth() ? screenWIDth - getWIDth() : x; // y = y < statusHeight ? statusHeight : (y + getHeight() >= screenHeight ? screenHeight - getHeight() : y); if (y<0){ y=0; } if (y>screenHeight-statusHeight-getHeight()){ y=screenHeight-statusHeight-getHeight(); } setX(x); setY(y); lastX = rawX; lastY = rawY; Log.e("move---->","getX=" + getX() + ";screenWIDthHalf=" + screenWIDthHalf + " " + isDrag+" statusHeight="+statusHeight+ " virtualHeight"+virtualHeight+ " screenHeight"+ screenHeight+" getHeight="+getHeight()+" y"+y); break; case MotionEvent.ACTION_UP: if (isDrag) { //恢复按压效果 setpressed(false); Log.e("ACTION_UP---->","getX=" + getX() + ";screenWIDthHalf=" + screenWIDthHalf); if (rawX >= screenWIDthHalf) { animate().setInterpolator(new DecelerateInterpolator()) .setDuration(500) .xBy(screenWIDth - getWIDth() - getX()) .start(); } else { ObjectAnimator oa = ObjectAnimator.offloat(this,"x",getX(),0); oa.setInterpolator(new DecelerateInterpolator()); oa.setDuration(500); oa.start(); } } Log.e("up---->",isDrag+""); break; } //如果是拖拽则消耗事件,否则正常传递即可。 return isDrag || super.ontouchEvent(event); }}
ScreenUtils.Java
package com.example.cmos.retrofitdemo;import androID.app.Activity;import androID.content.Context;import androID.graphics.Rect;import androID.util.displayMetrics;import androID.vIEw.display;import androID.vIEw.Window;import androID.vIEw.WindowManager;import java.lang.reflect.Method;/** * Created by gongwq on 2017/6/14 0014. */public class ScreenUtils { private ScreenUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 获得屏幕高度 * * @param context * @return */ public static int getScreenWIDth(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); displayMetrics outMetrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(outMetrics); return outMetrics.wIDthPixels; } /** * 获得屏幕宽度 * * @param context * @return */ public static int getScreenHeight(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); displayMetrics outMetrics = new displayMetrics(); wm.getDefaultdisplay().getMetrics(outMetrics); return outMetrics.heightPixels; } /** * 获得状态栏的高度 * * @param context * @return */ public static int getStatusHeight(Context context) { int statusHeight = -1; try { Class<?> clazz = Class.forname("com.androID.internal.R$dimen"); Object object = clazz.newInstance(); int height = Integer.parseInt(clazz.getFIEld("status_bar_height") .get(object).toString()); statusHeight = context.getResources().getDimensionPixelSize(height); } catch (Exception e) { e.printstacktrace(); } return statusHeight; } /** * 获取虚拟功能键高度 */ public static int getVirtualbarHeigh(Context context) { int vh = 0; WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); display display = windowManager.getDefaultdisplay(); displayMetrics dm = new displayMetrics(); try { @SuppressWarnings("rawtypes") Class c = Class.forname("androID.vIEw.display"); @SuppressWarnings("unchecked") Method method = c.getmethod("getRealMetrics",displayMetrics.class); method.invoke(display,dm); vh = dm.heightPixels - windowManager.getDefaultdisplay().getHeight(); } catch (Exception e) { e.printstacktrace(); } return vh; } public static int getVirtualbarHeigh(Activity activity) { int TitleHeight = 0; Rect frame = new Rect(); activity.getwindow().getDecorVIEw().getwindowVisibledisplayFrame(frame); int statusHeight = frame.top; TitleHeight = activity.getwindow().findVIEwByID(Window.ID_ANDROID_CONTENT).gettop() - statusHeight; return TitleHeight; }}
上面的代码也很简单,相信看代码中的注释就可以看的明白了。但是这里还是讲下其实现原理:这个自定义的悬浮按钮,我们主要是重写了其ontouch事件,捕捉触摸事件,然后利用setX(),setY()方法将其移动。而吸附效果,主要是利用的属性动画,最后,不要忘了return 是否还在拖拽的结果,免得无法触发点击事件。
PS
最后贴一个d出框。推荐用popmenu,相比于popwindow,这个会自动调整显示的位置,这在拖拽的悬浮按钮中很有用,因为如果用后者,你将按钮移到屏幕上方,而当你的d出框也是设置在显示的悬浮按钮的上方,那么就有可能会遮挡d出框的内容。
dragfloatActionbutton= (DragfloatActionbutton) findVIEwByID(R.ID.floatBtn); dragfloatActionbutton.setonClickListener(this);.... @OverrIDe public voID onClick(VIEw vIEw) { switch (vIEw.getID()) { case R.ID.floatBtn: PopupMenu popupMenu=new PopupMenu(this,vIEw); getMenuInflater().inflate(R.menu.pop_item,popupMenu.getMenu()); popupMenu.setonMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @OverrIDe public boolean onMenuItemClick(MenuItem menuItem) { switch (menuItem.getItemID()){ case R.ID.action_last: Toast.makeText(TestActivity.this,""+menuItem.getItemID(),Toast.LENGTH_SHORT).show(); break; case R.ID.action_next: Toast.makeText(TestActivity.this,Toast.LENGTH_SHORT).show(); break; } return false; } }); popupMenu.show(); Log.e("****--->","float"); // Toast.makeText(this,"flaot---",Toast.LENGTH_SHORT).show(); break; } }
新建menu文件夹,在里面添加pop_item.xml文件
<?xml version="1.0" enCoding="utf-8"?><menu xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:app="http://schemas.androID.com/apk/res-auto"> <item androID:ID="@+ID/action_delete" androID:orderIncategory="100" androID:title="删除" app:showAsAction="never" /> <item androID:ID="@+ID/action_save" androID:orderIncategory="200" androID:title="保存" app:showAsAction="never" /> <item androID:ID="@+ID/action_last" androID:orderIncategory="300" androID:title="上一步" app:showAsAction="never" /> <item androID:ID="@+ID/action_next" androID:icon="@null" androID:orderIncategory="400" androID:title="下一步" app:showAsAction="never" /></menu>
以上所述是小编给大家介绍的AndroID自定义可拖拽的悬浮按钮DragfloatingActionbutton,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android自定义可拖拽的悬浮按钮DragFloatingActionButton全部内容,希望文章能够帮你解决Android自定义可拖拽的悬浮按钮DragFloatingActionButton所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)