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