Android自定義View實(shí)現(xiàn)拖動選擇按鈕
更新時(shí)間:2016年05月27日 10:41:29 作者:pengkv
這篇文章主要為大家詳細(xì)介紹了Android自定義View實(shí)現(xiàn)拖動選擇按鈕的具體代碼,感興趣的小伙伴們可以參考一下
本文為大家分享了Android實(shí)現(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é)點(diǎn)數(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;//開始拖動的觸點(diǎn)坐標(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();
}
/**
*視圖初始化,這個(gè)方法的作用是把所有的視圖添加進(jìn)來,并做一些初始化的配置
* 其實(shí)可以用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);
}
/**
*這一步主要是為了測量、配置每個(gè)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);
}
}
}
/**
*這一步主要是為了放置每個(gè)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實(shí)現(xiàn)ImageView圖片縮放和拖動
- Android實(shí)現(xiàn)跟隨手指拖動并自動貼邊的View樣式(實(shí)例demo)
- Android實(shí)現(xiàn)單頁面浮層可拖動view的一種方法
- Android通過自定義ImageView控件實(shí)現(xiàn)圖片的縮放和拖動的實(shí)現(xiàn)代碼
- Android開發(fā)實(shí)現(xiàn)可拖動排序的ListView功能【附源碼下載】
- Android DragImageView實(shí)現(xiàn)下拉拖動圖片放大效果
- Android RecyclerView滑動刪除和拖動排序
- Android ViewDragHelper仿淘寶拖動加載效果
- Android自定義View圓形和拖動圓、跟隨手指拖動效果
- android實(shí)現(xiàn)可拖動的浮動view
相關(guān)文章
Android自定義View實(shí)現(xiàn)體重表盤詳解流程
對于安卓程序員來說,自定義view簡直不要太重要,畢竟有很多功能,譬如圓形頭像這些,用單純的原生非常難以實(shí)現(xiàn),而用自定義view,簡直分分鐘2021-11-11
Kotlin超簡單實(shí)現(xiàn)StepView的方法
這篇文章主要介紹了Kotlin超簡單實(shí)現(xiàn)StepView的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
一文帶你搞清楚Android游戲發(fā)行切包資源ID那點(diǎn)事
這篇文章主要介紹了Android 解決游戲發(fā)行切包資源ID的一些問題,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2023-05-05
Android中GPS坐標(biāo)轉(zhuǎn)換為高德地圖坐標(biāo)詳解
最近因?yàn)楣拘枨?,在做GPS定位,并且將獲得的坐標(biāo)顯示在高德地圖上,但是實(shí)際效果跟我們期望的是有偏差的。通過查閱資料,才知道有地球坐標(biāo)、火星坐標(biāo)之說。下面這篇文章就詳細(xì)介紹了Android中GPS坐標(biāo)轉(zhuǎn)換為高德地圖坐標(biāo)的方法,需要的朋友可以參考下。2017-01-01
使用Fragment+ViewPager實(shí)現(xiàn)底部導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了使用Fragment+ViewPager實(shí)現(xiàn)底部導(dǎo)航欄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06

