您的位置:首页 > 其它

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

2016-04-23 11:21 232 查看

效果图



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();
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: