首页 > 系统 > Android > 正文

Android自定义View实现等级滑动条的实例

2019-12-12 03:03:14
字体:
来源:转载
供稿:网友

 Android自定义View实现等级滑动条的实例

实现效果图:

思路:

首先绘制直线,然后等分直线绘制点;

绘制点的时候把X值存到集合中。

然后绘制背景图片,以及图片上的数字。

点击事件down的时候,换小图片为大图片。move的时候跟随手指移动。

up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去。

1,自定义属性

<?xml version="1.0" encoding="utf-8"?><resources>   <declare-styleable name="BeautySeekBarView">     <attr name="valueCountent" format="integer"/>      <attr name="padding" format="dimension"/>       <attr name="pointColor" format="color"/>     <attr name="lineColor" format="color"/>    <attr name="smallPic" format="reference"/>     <attr name="bigPic" format="reference"/>    </declare-styleable> </resources>

然后获取属性:

 /**      * 获得我们所定义的自定义样式属性      */     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.BeautySeekBarView, defStyleAttr, 0);    //等级数量即点的个数    valueCountent=a.getInteger(R.styleable.BeautySeekBarView_valueCountent, 5);    //点的颜色    pointColor = a.getColor(R.styleable.BeautySeekBarView_pointColor, Color.WHITE);     //线的颜色    lineColor = a.getColor(R.styleable.BeautySeekBarView_lineColor, Color.WHITE);    //小图片    smallPic=a.getResourceId(R.styleable.BeautySeekBarView_smallPic, R.drawable.ic_launcher);    //滑动过程中的大图片    bigPic=a.getResourceId(R.styleable.BeautySeekBarView_bigPic, R.drawable.ic_launcher);      //控件的内边距    viewPadding=a.getDimensionPixelSize(R.styleable.BeautySeekBarView_padding, (int) TypedValue.applyDimension(             TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));    a.recycle();    

2.绘制

@Override  protected void onDraw(Canvas canvas) {    // TODO Auto-generated method stub    super.onDraw(canvas);    float PointX = 0;    float PointY=getHeight()/2;       canvas.drawLine(0+getPaddingLeft(),PointY, getWidth()-getPaddingRight(), PointY, linePaint); //绘制直线    int averageLength =(getWidth()-getPaddingLeft()-getPaddingRight())/(valueCountent-1);    for(int i=0;i<valueCountent;i++){      PointX=i*averageLength+getPaddingLeft();      canvas.drawPoint(PointX, PointY, pointPaint);//绘制点      if(pointList!=null && pointList.size()<valueCountent){      pointList.add(PointX);//把每个点都放入集合中;      }          }    sePoolTH.release();    canvas.drawBitmap(mBitmap, bitmapPointX-bitmapWidth/2, PointY-bitmapHeight/2, null);//绘制拖动的图片     canvas.drawText(""+index, bitmapPointX, (getHeight() - fontMetrics.ascent - fontMetrics.descent) / 2, textPaint); //绘制文字  }

全部代码如下

import java.util.ArrayList;import java.util.HashMap;import java.util.concurrent.Semaphore;import android.R.integer;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetricsInt;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.MotionEvent;import android.view.View;public class BeautySeekBarView extends View {  private Semaphore sePoolTH=new Semaphore(0);//信号量,解决并发问题  private int valueCountent;//等级点的数量  private int pointColor;  private int lineColor;  private Bitmap mBitmap;  private int bitmapWidth;  private int bitmapHeight;  private float bitmapPointX;  private ArrayList<Float> pointList;//储存画出的点的point值  private HashMap<Float, Float> mHashMap;////把差值和listX当做键值对保存起来,便于后期找出  private int index=1;//索引  private float mListX;//移动后最小的点  private int smallPic;  private int bigPic;  private int viewPadding;   private Paint pointPaint;  private Paint linePaint;  private Paint textPaint;  private FontMetricsInt fontMetrics;  public BeautySeekBarView(Context context) {    this(context,null);     }  public BeautySeekBarView(Context context, AttributeSet attrs) {    this(context, attrs,0);     }  public BeautySeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);             /**      * 获得我们所定义的自定义样式属性      */     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.BeautySeekBarView, defStyleAttr, 0);    //等级数量即点的个数    valueCountent=a.getInteger(R.styleable.BeautySeekBarView_valueCountent, 5);    //点的颜色    pointColor = a.getColor(R.styleable.BeautySeekBarView_pointColor, Color.WHITE);     //线的颜色    lineColor = a.getColor(R.styleable.BeautySeekBarView_lineColor, Color.WHITE);    //小图片    smallPic=a.getResourceId(R.styleable.BeautySeekBarView_smallPic, R.drawable.ic_launcher);    //滑动过程中的大图片    bigPic=a.getResourceId(R.styleable.BeautySeekBarView_bigPic, R.drawable.ic_launcher);      //控件的内边距    viewPadding=a.getDimensionPixelSize(R.styleable.BeautySeekBarView_padding, (int) TypedValue.applyDimension(             TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));    a.recycle();        initData();//初始化数据     initPaint();//初始化画笔    }  public void initData() {//   valueCountent=7;//   pointColor=Color.WHITE;//   lineColor=Color.WHITE;     //   setBackgroundColor(Color.BLACK);        setPadding(viewPadding, viewPadding, viewPadding, viewPadding);    bitmapPointX=getPaddingLeft();    mBitmap=BitmapFactory.decodeResource(getResources(), smallPic);    bitmapWidth=mBitmap.getWidth();    bitmapHeight=mBitmap.getHeight();    pointList=new ArrayList<Float>();    mHashMap=new HashMap<Float, Float>();  }  public void initPaint() {    pointPaint=new Paint();    pointPaint.setColor(pointColor);    pointPaint.setStyle(Paint.Style.FILL);    pointPaint.setStrokeWidth(10);    pointPaint.setStrokeJoin(Paint.Join.ROUND);    pointPaint.setStrokeCap(Paint.Cap.ROUND);    pointPaint.setAntiAlias(true);     linePaint=new Paint();    linePaint.setColor(lineColor);    linePaint.setStyle(Paint.Style.STROKE);    linePaint.setStrokeWidth(4);    linePaint.setAntiAlias(true);     textPaint=new Paint();    textPaint.setStrokeWidth(3);      textPaint.setTextSize(24);      textPaint.setColor(Color.WHITE);     textPaint.setTextAlign(Paint.Align.CENTER);        fontMetrics = textPaint.getFontMetricsInt();     textPaint.setAntiAlias(true);   }@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  // TODO Auto-generated method stub  super.onMeasure(widthMeasureSpec, heightMeasureSpec);}  @Override  protected void onDraw(Canvas canvas) {    // TODO Auto-generated method stub    super.onDraw(canvas);    float PointX = 0;    float PointY=getHeight()/2;       canvas.drawLine(0+getPaddingLeft(),PointY, getWidth()-getPaddingRight(), PointY, linePaint); //绘制直线    int averageLength =(getWidth()-getPaddingLeft()-getPaddingRight())/(valueCountent-1);    for(int i=0;i<valueCountent;i++){      PointX=i*averageLength+getPaddingLeft();      canvas.drawPoint(PointX, PointY, pointPaint);//绘制点      if(pointList!=null && pointList.size()<valueCountent){      pointList.add(PointX);//把每个点都放入集合中;      }          }    sePoolTH.release();    canvas.drawBitmap(mBitmap, bitmapPointX-bitmapWidth/2, PointY-bitmapHeight/2, null);//绘制拖动的图片     canvas.drawText(""+index, bitmapPointX, (getHeight() - fontMetrics.ascent - fontMetrics.descent) / 2, textPaint); //绘制文字  }  long startTime = 0;  @Override  public boolean onTouchEvent(MotionEvent event) {               //获取手指的操作--》按下、移动、松开        int action = event.getAction();        switch (action) {        case MotionEvent.ACTION_DOWN:            startTime=System.currentTimeMillis();          mBitmap=BitmapFactory.decodeResource(getResources(), bigPic);          bitmapWidth=mBitmap.getWidth();          bitmapHeight=mBitmap.getHeight();          textPaint.setTextSize(30);           //invalidate();          break;               case MotionEvent.ACTION_MOVE:                  long endTimeMove=System.currentTimeMillis();                  if(endTimeMove-startTime>100){//如果按下,抬起时间过大才认为是拖动,要执行动画。           bitmapPointX=event.getX();           updateIndex(bitmapPointX);           invalidate();          }          break;        case MotionEvent.ACTION_UP:          long endTime=System.currentTimeMillis();          bitmapPointX=event.getX();          mBitmap=BitmapFactory.decodeResource(getResources(),smallPic);          bitmapWidth=mBitmap.getWidth();          bitmapHeight=mBitmap.getHeight();          textPaint.setTextSize(24);                       if(endTime-startTime>200){//如果按下,抬起时间过大才认为是拖动,要执行动画。          updateBitmapUI(bitmapPointX);          }else{                       bitmapPointX=updateIndex(bitmapPointX);            invalidate();          }          startTime = 0;          break;        }        return true;  }  //更新索引  public float updateIndex(float pointX){    float lastValue=100000;    float currentValue=0;    float minValue=0;     for(float listX:pointList){       currentValue= Math.abs(pointX-listX);       mHashMap.put(currentValue, listX);//把差值和listX当做键值对保存起来,便于后期找出       minValue=Math.min(lastValue,currentValue);       lastValue=minValue;      }          if(mHashMap.containsKey(minValue)){      mListX=mHashMap.get(minValue);    }else{      Log.e("BeautySeekBarView", "updateBitmapUI--->mHashMap.containsKey(minValue) is null");      return -1;    }     if(pointList.contains(mListX)){    index=pointList.indexOf(mListX)+1;    if(mListener!=null){      mListener.getIndex(index);    }    }else{      Log.e("BeautySeekBarView", "updateBitmapUI--->pointList.contains(mListX) is null");        return -1;    }    return mListX;  }  //当手指抬起后更新Bitmap的位置  private void updateBitmapUI(float PointX2) {    mListX=updateIndex(PointX2);    //执行动画       ValueAnimator anim = ValueAnimator.ofFloat(PointX2, mListX);    anim.setDuration(50);    anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator animation) {        bitmapPointX =(Float) animation.getAnimatedValue();        invalidate();      }    });    anim.start();  }  //设置等级点的数量  public void pointValueCountent(int countent){    if(countent<2){      valueCountent=2;    }else{      valueCountent=countent;    }    invalidate();  }  //设置默认位置  public void setPointLocation(final int location){    new Thread(new Runnable() {      @Override      public void run() {                try {            sePoolTH.acquire();          } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();          }              if(location>0&&pointList!=null&& !pointList.isEmpty()){            bitmapPointX=pointList.get(location-1);            postInvalidate();          }      }    }).start();  }  //提供接口回调,获取索引  private indexListener mListener=null;  public interface indexListener{    void getIndex(int index);  }  public void setIndexListener(indexListener listener){    mListener=listener;  }}

外部调用:

XML:

 <com.example.hello.BeautySeekBarView     android:id="@+id/myView"    android:layout_centerVertical="true"    android:layout_width="match_parent"    android:layout_height="100dp"    ws:padding="20dp"         ws:valueCountent="6"       ws:pointColor="#FFFFFF"    ws:lineColor="#FFFFFF"    ws:smallPic="@drawable/beauty_seekbar_point"    ws:bigPic="@drawable/beauty_seekbar_point_big"/>

Java:

@Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);      setContentView(R.layout.activity_main);   initView();    beautySeekBarView.setPointLocation(2) ;    //  }  private void initView() {  mTextView=(TextView) findViewById(R.id.tv);  beautySeekBarView=(BeautySeekBarView) findViewById(R.id.myView);  beautySeekBarView.setIndexListener(new indexListener() {      @Override    public void getIndex(int index) {      mTextView.setText("index="+index);     }  });  }

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表