自定义View-5-拖动选择按钮

来源:互联网 发布:运用python成为黑客 编辑:程序博客网 时间:2024/05/23 19:20

效果图

这里写图片描述

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 {    /**     * 默认颜色     */    private final int DEFAULT_COLOR = Color.LTGRAY;    /**     * 默认半径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;//拖动图标    private ImageView mDragView;//拖动图标ImageView    private int mCircleColor;//圆的颜色    private Context mContext;//上下文    private int mDotNum;//节点数量    private int mWidth;//组件的宽度    private int mHight;//组件的高度    private int mCircleRadius;//园的半径    private int mDragWidth;//拖动图标的宽度    private int mLineWidth,mLineHeight;//中间线的长宽    private float mStartX;//开始拖动的屏幕坐标    private float mCurX;//开始拖动的触点坐标    private float mMinX;//拖动范围的最小值    private float mMaxX;//拖动范围的最大值    private OnNodeSelect mOnNodeSelect;//回调接口    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();    }    /**     *视图初始化,这个方法的作用是把所有的视图添加进来,并做一些初始化的配置     * 其实可以用LayoutInflater把xml的布局文件加载进来,这样比较简便     */    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;    }    //设置平移动画    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;    }    //事件回调接口    public interface OnNodeSelect {        void onNodeSelect(int position);    }    //dp转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();     } });
2 0
原创粉丝点击