Android自定义可拖拽的悬浮按钮DragFloatingActionButton

Android自定义可拖拽的悬浮按钮DragFloatingActionButton,第1张

概述悬浮按钮FloatingActionButton是Android5.0系统添加的新控件,FloatingActionButton是继承至ImageView,所以FloatingActionButton拥有ImageView的所有属性。本文讲解的是一个实现了可拖拽的悬浮按钮,并为此添加了类似

悬浮按钮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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1145974.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存