Android实现可移动的自定义浮动按钮

    xiaoxiao2021-04-12  30

    public class RootView extends RelativeLayout { private Context mContext; /**----------可配置属性-------------------*/ /** * 控制窗口是否能移动 */ private static boolean canMove = true; /** * 是否显示文字 *  注意:在isDisplayFont=true才生效 */ private static boolean isDisplayFont = true; /** * 是否支持长按后才可以移动 */ private static boolean isCanLongTouchMove = true; /** * 悬浮按钮上的文字 *  注意:在isDisplayFont=true才生效 */ private static String mFont = "标题"; /** * 文字大小 *  注意:在isDisplayFont=true才生效 */ private float mFontSize=12; /** * 文字的颜色 *  注意:在isDisplayFont=true才生效 */ private String mFontColor="#000000"; /** * 文字背景颜色 *  注意:在isDisplayFont=true才生效 */ private String mFontBgColor="#f24B8DF4"; /** * 是否显示文本背景颜色 *  注意:在isDisplayFont=true才生效 */ private boolean isDisplayFontBgColor=true; /** * 浮动按钮的背景图片 */ private  int mIconId=R.drawable.floatbar; /** * 浮动按钮的大小 */ private  int mWidthAndHeight = 200; /** *显示文字的高度,只有在isDisplayFont=true是才生效 */ private  int mDisplayFontHeight = 80; /**---------------不可配置属性-----------------------*/ private static boolean isMoving = false; private static boolean isIntercepted = false; private static boolean isInsideImageView = false; private static boolean isClickedOnImage = false; private static boolean onLongTouchCanMove = false; private int imageId = 001; private View mMageView = null; private static final int ON_PLACE_CHANGED=1; private static final int ON_LONG_TOUCH=100; private static final int ON_REFRISH_CANVAS=101; private Timer mTimer;//计时用 private static int mTimesNumber=0; private Handler mHandler = new Handler(Looper.getMainLooper()){      @Override     public void handleMessage(Message msg) {      super.handleMessage(msg);          int id=msg.what;          switch (id){              case ON_LONG_TOUCH:                  onLongTouchCanMove=true;                  break;             case ON_PLACE_CHANGED:                  break;             case ON_REFRISH_CANVAS:                 mMageView.requestLayout();                  break;          }     }  }; private int sX = 0, sY = 0, eX = 0, eY = 0, mDistanceX = 0, mDistanceY = 0, mMarginTop = 0, mMarginLeft = 0, mPadding = 5, mScreenHeight = 0, mScreenWidth = 0, mOffset = 200; public RootView(Context context) {      this(context, null); } public RootView(Context context, AttributeSet attrs) {     this(context, attrs, 0); } public RootView(Context context, AttributeSet attrs, int defStyleAttr) {     super(context, attrs, defStyleAttr);     mContext = context;     init(); } private void init() {     mHandler.post(new Runnable() {       @Override         public void run() {            SystemClock.sleep(2000);            initView();       } }); DisplayMetrics mDisplayMetrics = mContext.getResources().getDisplayMetrics();     if (isDisplayFont) {        mScreenWidth = mDisplayMetrics.widthPixels;        mScreenHeight = mDisplayMetrics.heightPixels;        mMarginLeft = mScreenWidth - mWidthAndHeight - mOffset / 2;        mMarginTop = mScreenHeight - mWidthAndHeight - getStatusBarHeight() - mOffset-mDisplayFontHeight;     } else {        mScreenWidth = mDisplayMetrics.widthPixels;        mScreenHeight = mDisplayMetrics.heightPixels;        mMarginLeft = mScreenWidth - mWidthAndHeight - mOffset / 2;       mMarginTop = mScreenHeight - mWidthAndHeight - getStatusBarHeight() - mOffset; } } private void initView() {  MyView mImage = new MyView(mContext);  LayoutParams mFloatLayout = new LayoutParams(mWidthAndHeight, mWidthAndHeight);  mFloatLayout.leftMargin = mMarginLeft;  mFloatLayout.topMargin = mMarginTop;  mFloatLayout.addRule(Gravity.CENTER);  mImage.setLayoutParams(mFloatLayout);  mImage.setId(imageId);  mFloatLayout.addRule(Gravity.CENTER);  mImage.setGravity(Gravity.CENTER);  setViewOnClick(mImage); ImageView mImageView = new ImageView(mContext);   LayoutParams imageLayout = new LayoutParams(mWidthAndHeight, mWidthAndHeight);   imageLayout.leftMargin = mPadding;   imageLayout.rightMargin = mPadding;   imageLayout.bottomMargin = mPadding+2;   imageLayout.topMargin = mPadding;   imageLayout.addRule(RelativeLayout.CENTER_IN_PARENT);   mImageView.setImageResource(mIconId);   imageLayout.addRule(Gravity.CENTER);   mImageView.setLayoutParams(imageLayout);   mImage.addView(mImageView);   int mChildCount = getChildCount(); if (isDisplayFont) {   LinearLayout outer = new LinearLayout(mContext);   outer.setOrientation(LinearLayout.VERTICAL);   LayoutParams mRoot = new LayoutParams(mWidthAndHeight, mWidthAndHeight+mDisplayFontHeight);   mRoot.leftMargin = mMarginLeft;   mRoot.topMargin = mMarginTop;   outer.setLayoutParams(mRoot);   TextView title = new TextView(mContext);   LayoutParams mTitleLayout = new LayoutParams(LayoutParams.MATCH_PARENT, mDisplayFontHeight);   title.setText(mFont);    if (isDisplayFontBgColor){       title.setBackgroundColor(Color.parseColor(mFontBgColor));     }   title.setTextSize(mFontSize);   title.setTextColor(Color.parseColor(mFontColor));   mTitleLayout.bottomMargin=3;   title.setGravity(Gravity.CENTER);   title.setLayoutParams(mTitleLayout);   outer.addView(mImage);   outer.addView(title);   this.addView(outer, mChildCount);   mMageView = outer;   } else {     this.addView(mImage, mChildCount);     mMageView = mImage;   } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) {   return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent ev) {  if (mMageView == null) {      int mChildCount = getChildCount();       for (int i = 0; i < mChildCount; i++) {           if (getChildAt(i) instanceof MyView) {               mMageView = getChildAt(i);           }        }     }     if (isInterceptEvent(ev)) {         return true;     } else {        return super.dispatchTouchEvent(ev);     } } @Override public boolean onTouchEvent(MotionEvent event) {    if (isIntercepted) {         isInterceptEvent(event);         return isIntercepted;     } else {         return super.onTouchEvent(event);     } } private void reset(){     mTimesNumber=0;     onLongTouchCanMove=false;     if (mTimer!=null){         try {            mTimer.cancel();          mTimer=null;       } catch (Exception e) {           mTimer=null;      }   }else {        mTimer=null;    }     System.gc(); } private void calculateTime(){   if (mTimer==null){        mTimer=new Timer();        mTimer.schedule(new TimerTask() {            @Override          public void run() {             mTimesNumber++;              if (mTimesNumber==5){                  mHandler.sendEmptyMessage(ON_LONG_TOUCH);                 try {                      mTimer.cancel();                       mTimer=null;                 } catch (Exception e) {                       e.printStackTrace();                 } finally {                       mTimer=null;                   }                }            }       },0,100);    } } private boolean isInterceptEvent(MotionEvent event) {   switch (event.getAction()) {       case MotionEvent.ACTION_DOWN:          if (mMageView != null) {               mMageView.setClickable(true);          }          isIntercepted = true;          sX = (int) event.getX();          sY = (int) event.getY();         if (isCanLongTouchMove){             calculateTime();        }       mHandler.sendEmptyMessage(ON_REFRISH_CANVAS);        break;    case MotionEvent.ACTION_MOVE:         isMoving = true;        eX = (int) event.getX();        eY = (int) event.getY();        mDistanceX = eX - sX;        mDistanceY = eY - sY;        sX = eX;        sY = eY;        if (isInsideImageView) {             if (canMove) {                calculate(mDistanceX, mDistanceY);               }          }                     break;       case MotionEvent.ACTION_UP:          isInsideImageView = false;         isIntercepted = false;         sX = 0;         sY = 0;         if (isMoving) {             isClickedOnImage = false;              } else {                isClickedOnImage = true;            }           if (mMageView != null) {                mMageView.setClickable(isClickedOnImage);            }           isMoving = false;            if (isCanLongTouchMove){                reset();            }          break;   }  if (!isInsideImageView) {     if (isCanLongTouchMove){           if (onLongTouchCanMove ){              isTouchIn(sX, sY);                 }             }else {                 isTouchIn(sX, sY);             }         }         if (isInsideImageView && isMoving) {             return true;         } else {             return false;  } } private boolean isTouchIn(int sX, int sY) { if (isDisplayFont){ if ((sX >= mMarginLeft && sX <= (mMarginLeft + mWidthAndHeight)) && (sY >= mMarginTop && sY <= (mMarginTop + mWidthAndHeight))) {           isInsideImageView = true;            return true;    } else {          isInsideImageView = false;           return false;       }  }else {       if ((sX >= mMarginLeft && sX <= (mMarginLeft + mWidthAndHeight)) && (sY >= mMarginTop && sY <= (mMarginTop + mWidthAndHeight))) {           isInsideImageView = true;              return true;       } else {           isInsideImageView = false;           return false;      }    } } private void setViewOnClick(MyView viewOnClick) {     viewOnClick.setOnClickListener(new OnClickListener() {         @Override         public void onClick(View v) {             if (isClickedOnImage) {                isClickedOnImage = false;                onFloatingBarClicked();            }      }   }); } class MyView extends RelativeLayout {     Paint mPaint;    public MyView(Context context) {      this(context, null);   } public MyView(Context context, AttributeSet attrs) {   this(context, attrs, 0); } public MyView(Context context, AttributeSet attrs, int defStyleAttr) {   super(context, attrs, defStyleAttr);   init();  } private void init() {   this.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#00000000")));    mPaint = new Paint();    if (isIntercepted){        mPaint.setColor(Color.parseColor("#7C7784"));      }else {         mPaint.setColor(Color.parseColor("#A8B6AD"));     }     mPaint.setStrokeJoin(Paint.Join.ROUND);     mPaint.setStrokeCap(Paint.Cap.ROUND);     mPaint.setStrokeWidth(3); } @Override protected void onDraw(Canvas canvas) {     super.onDraw(canvas);        canvas.drawCircle(mWidthAndHeight/2, mWidthAndHeight/2, mWidthAndHeight/2-3, mPaint);      } } private void calculate(int distanceX, int distanceY) {  if (isDisplayFont) {      if ((mMarginTop <= mScreenHeight -mDisplayFontHeight-getStatusBarHeight()) && (mMarginTop >= 1)) {        mMarginTop = mMarginTop + distanceY;       }      if ((mMarginLeft >= 1) && (mMarginLeft <= mScreenWidth - mWidthAndHeight)) {         mMarginLeft = mMarginLeft + distanceX;      } } else {      if ((mMarginTop <= mScreenHeight - mWidthAndHeight) && (mMarginTop >= 1 )) {         mMarginTop = mMarginTop + distanceY;      }      if ((mMarginLeft >= 1) && (mMarginLeft <= mScreenWidth - mWidthAndHeight)) {        mMarginLeft = mMarginLeft + distanceX;         }      }     startMove(); } private void startMove() {   if (mMageView != null) {        if (isDisplayFont) {            if (mMarginTop >= mScreenHeight - mWidthAndHeight-mDisplayFontHeight-getStatusBarHeight()) {                mMarginTop = mScreenHeight - mWidthAndHeight-mDisplayFontHeight-getStatusBarHeight()-5 ;          } else if (mMarginTop < 1) {          mMarginTop = 2;       }     }else {          if (mMarginTop >= mScreenHeight - mWidthAndHeight-getStatusBarHeight()) {            mMarginTop = mScreenHeight - mWidthAndHeight-getStatusBarHeight()-5;          } else if (mMarginTop <1) {            mMarginTop = 2;         }      }        if (mMarginLeft <=1) {        mMarginLeft = 2;     } else if (mMarginLeft >= mScreenWidth - mWidthAndHeight) {        mMarginLeft = mScreenWidth - mWidthAndHeight-2;     }         LayoutParams mLayoutParams = (LayoutParams) mMageView.getLayoutParams();         mLayoutParams.leftMargin = mMarginLeft;         mLayoutParams.topMargin = mMarginTop;         mMageView.setLayoutParams(mLayoutParams);    } } private int getStatusBarHeight() {    Class<?> c = null;    Object obj = null;    Field field = null;    int x = 0, sbar = 0;    try {       c = Class.forName("com.android.internal.R$dimen");       obj = c.newInstance();        field = c.getField("status_bar_height");        x = Integer.parseInt(field.get(obj).toString());        sbar = getContext().getResources().getDimensionPixelSize(x);     } catch (Exception e1) {        e1.printStackTrace();    }    return sbar;  } /** * 点击事件 */ public void onFloatingBarClicked() {  //TODO .......    Toast.makeText(mContext, "被点击", Toast.LENGTH_SHORT).show();  }

    }

    布局使用:

    <com.example.floatbar.RootView android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent"></ListView> </RelativeLayout>

    自定义view组件在布局中使用的时候只能作为容器的父布局,字容器可以用任意多个,且父容器是相对布局

    效果图:

    转载请注明原文地址: https://ju.6miu.com/read-667478.html

    最新回复(0)