Android自定義View實現(xiàn)拖動選擇按鈕
本文為大家分享了Android實現(xiàn)拖動選擇按鈕的具體代碼,供大家參考,具體內(nèi)容如下
效果圖
View代碼
第一步:自定義屬性
<declare-styleable name="DragView"> <attr name="icon_drag" format="reference"/> <attr name="color_circle" format="color"/> <attr name="dot_num" format="integer"/> </declare-styleable>
第二步:自定義圓形
public class CircleView extends View { /** * 默認(rèn)顏色 */ private final int DEFAULT_COLOR = Color.LTGRAY; /** * 默認(rèn)半徑dp */ private final float DEFAULT_RADIUS = 32; private int mColor; private Paint mCirclePaint; private float mRadius; private float mCenterX; private float mCenterY; public CircleView(Context context) { this(context, null); } public CircleView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.DragView); mColor = array.getColor(R.styleable.DragView_color_circle,DEFAULT_COLOR); mCirclePaint = new Paint(); mCirclePaint.setColor(mColor); mCenterY = mCenterX = mRadius = getMeasuredWidth() == 0?DEFAULT_RADIUS:getMeasuredWidth()/2; array.recycle(); } public float getRadius(){ return mRadius; } public int getColor() { return mColor; } @Override protected void onDraw(Canvas canvas) { canvas.drawCircle(mCenterX,mCenterY,mRadius,mCirclePaint); } }
第三步:自定義拖動按鈕
public class DragView extends RelativeLayout implements View.OnTouchListener { private Drawable mDragIcon;//拖動圖標(biāo) private ImageView mDragView;//拖動圖標(biāo)ImageView private int mCircleColor;//圓的顏色 private Context mContext;//上下文 private int mDotNum;//節(jié)點數(shù)量 private int mWidth;//組件的寬度 private int mHight;//組件的高度 private int mCircleRadius;//園的半徑 private int mDragWidth;//拖動圖標(biāo)的寬度 private int mLineWidth,mLineHeight;//中間線的長寬 private float mStartX;//開始拖動的屏幕坐標(biāo) private float mCurX;//開始拖動的觸點坐標(biāo) private float mMinX;//拖動范圍的最小值 private float mMaxX;//拖動范圍的最大值 private OnNodeSelect mOnNodeSelect;//回調(diào)接口 public DragView(Context context) { this(context,null); } public DragView(Context context, AttributeSet attrs) { this(context, attrs,0); } public DragView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.DragView); mDragIcon=array.getDrawable(R.styleable.DragView_icon_drag); mCircleColor=array.getColor(R.styleable.DragView_color_circle,Color.WHITE); mDotNum=array.getInt(R.styleable.DragView_dot_num,2); array.recycle(); mContext=context; initView(); } /** *視圖初始化,這個方法的作用是把所有的視圖添加進(jìn)來,并做一些初始化的配置 * 其實可以用LayoutInflater把xml的布局文件加載進(jìn)來,這樣比較簡便 */ public void initView(){ for (int i=0;i<mDotNum;i++){ CircleView circleView=new CircleView(mContext); circleView.setOnTouchListener(this); addView(circleView); } View view=new View(mContext); view.setBackgroundColor(mCircleColor); addView(view); // TODO: 2016/4/21 top not right mDragView=new ImageView(mContext); mDragView.setImageDrawable(mDragIcon); mDragView.setOnTouchListener(this); addView(mDragView); } /** *這一步主要是為了測量、配置每個view的大小,以便于后面觸摸事件的處理 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth=getMeasuredWidth(); mHight=getMeasuredHeight(); mCircleRadius=dp2px(mContext,32); mDragWidth=dp2px(mContext,50); mLineWidth=mWidth-mDragWidth; mLineHeight=mCircleRadius/2; int count=getChildCount(); for (int i=0;i<count;i++){ View view=getChildAt(i); LinearLayout.LayoutParams params; if (view instanceof CircleView){ params=new LinearLayout.LayoutParams(mCircleRadius,mCircleRadius); view.setLayoutParams(params); }else if (view instanceof ImageView){ params=new LinearLayout.LayoutParams(mDragWidth,mDragWidth); view.setLayoutParams(params); }else { params=new LinearLayout.LayoutParams(mLineWidth,mLineHeight); view.setLayoutParams(params); } } } /** *這一步主要是為了放置每個view的位置,如果用LayoutInflater加載布局文件,那這一步就可以省略了 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // super.onLayout(changed, l, t, r, b); if (changed){ int count =getChildCount(); int dLeft=0; int dTop=mHight/2-mDragWidth/2; int cLeft=mDragWidth/2-mCircleRadius/2; int cTop=dTop+mDragWidth/2-mCircleRadius/2; int lLeft=mDragWidth/2; int lTop=dTop+mDragWidth/2-mLineHeight/2; mMinX=dLeft; mMaxX=dLeft+mLineWidth; int cIndex=0; int cSpace=0; for (int i=0;i<count;i++){ View view=getChildAt(i); if (view instanceof CircleView){ cLeft=cLeft+cSpace; view.layout(cLeft,cTop,cLeft+mCircleRadius,cTop+mCircleRadius); cIndex++; cSpace=cIndex*mLineWidth; }else if (view instanceof ImageView){ view.layout(dLeft,dTop,dLeft+mDragWidth,dTop+mDragWidth); }else { view.layout(lLeft,lTop,lLeft+mLineWidth,lTop+mLineHeight); } } } } /** *觸碰事件的處理,這是自定義view比較重要的地方 */ @Override public boolean onTouch(View v, MotionEvent event) { if (v instanceof ImageView){ switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mStartX = (int) event.getRawX(); mCurX = v.getTranslationX();//獲取view的偏移量 v.setPressed(true); break; case MotionEvent.ACTION_MOVE: float x = mCurX + event.getRawX() - mStartX; if (x >= 0 && x <= mMaxX - mMinX) { v.setTranslationX(mCurX + event.getRawX() - mStartX); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: int distance=(int) (event.getRawX()-mStartX); if (distance>0){ if (Math.abs(distance)>mLineWidth/2){ v.setTranslationX(mCurX + event.getRawX() - mStartX); setAnim(mLineWidth,1); }else { v.setTranslationX(mCurX + event.getRawX() - mStartX); setAnim(0,0); } }else if (distance<0){ if (Math.abs(distance)>mLineWidth/2){ v.setTranslationX(mCurX + event.getRawX() - mStartX); setAnim(0,0); }else { v.setTranslationX(mCurX + event.getRawX() - mStartX); setAnim(mLineWidth,1); } } break; } }else if (v instanceof CircleView){ switch (event.getAction()) { case MotionEvent.ACTION_UP: if (event.getRawX()>getDisplayWidth()/2){ setAnim(mLineWidth,1); }else { setAnim(0,0); } break; } } return true; } //設(shè)置平移動畫 private void setAnim(float moveX, final int scrollPosition) { ObjectAnimator animator = ObjectAnimator.ofFloat(mDragView, "translationX", mDragView.getTranslationX(), moveX); animator.setDuration(300); animator.start(); if (mOnNodeSelect != null) { mOnNodeSelect.onNodeSelect(scrollPosition); } } public void setNodeSelectListener(OnNodeSelect onNodeSelect) { mOnNodeSelect = onNodeSelect; } //事件回調(diào)接口 public interface OnNodeSelect { void onNodeSelect(int position); } //dp轉(zhuǎn)px public int dp2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } //獲取屏幕寬度 public int getDisplayWidth(){ DisplayMetrics metrics=new DisplayMetrics(); ((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics); return metrics.widthPixels; } }
使用方法
布局文件:
<com.pengkv.apple.weight.DragView android:id="@+id/view_drag" android:layout_width="200dp" app:icon_drag="@drawable/ic_drag" app:color_circle="#CCCCCC" app:dot_num="2" android:layout_height="60dp"/>
頁面代碼:
dragView=(DragView)view.findViewById(R.id.view_drag); dragView.setNodeSelectListener(new DragView.OnNodeSelect() { @Override public void onNodeSelect(int position) { Toast.makeText(getActivity(),"我選擇了"+position,Toast.LENGTH_SHORT).show(); } });
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實現(xiàn)ImageView圖片縮放和拖動
- Android實現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實例demo)
- Android實現(xiàn)單頁面浮層可拖動view的一種方法
- Android通過自定義ImageView控件實現(xiàn)圖片的縮放和拖動的實現(xiàn)代碼
- Android開發(fā)實現(xiàn)可拖動排序的ListView功能【附源碼下載】
- Android DragImageView實現(xiàn)下拉拖動圖片放大效果
- Android RecyclerView滑動刪除和拖動排序
- Android ViewDragHelper仿淘寶拖動加載效果
- Android自定義View圓形和拖動圓、跟隨手指拖動效果
- android實現(xiàn)可拖動的浮動view
相關(guān)文章
Android Studio實現(xiàn)標(biāo)題欄和狀態(tài)欄的隱藏
這篇文章主要介紹了Android Studio實現(xiàn)標(biāo)題欄和狀態(tài)欄的隱藏功能,在文中給大家補充介紹了android studio 去掉標(biāo)題欄狀態(tài)欄的完整代碼,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-11-11Android自定義View實現(xiàn)跟隨手指移動的小兔子
這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)跟隨手指移動的小兔子,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-11-11深入理解Android熱修復(fù)技術(shù)原理之資源熱修復(fù)技術(shù)
Android資源的熱修復(fù),就是在app不重新安裝的情況下,利用下發(fā)的補丁包 直接更新本app中的資源2021-06-06Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解
這篇文章主要介紹了Kotlin之在Gradle中無參(no-arg)編譯器插件的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11Android Shape屬性創(chuàng)建環(huán)形進(jìn)度條
這篇文章主要介紹了Android Shape屬性創(chuàng)建環(huán)形進(jìn)度條的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11