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

来源:互联网 发布:java开发酒店管理系统 编辑:程序博客网 时间:2024/05/21 07:13


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组件在布局中使用的时候只能作为容器的父布局,字容器可以用任意多个,且父容器是相对布局



效果图:



0 0
原创粉丝点击