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

作者:小码哥_WS 时间:2023-12-08 19:57:53 

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

实现效果图:

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);

}

@Override
protected 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);
   }
 });
 }

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

来源:http://blog.csdn.net/king1425/article/details/53444649

标签:Android,等级滑动条
0
投稿

猜你喜欢

  • Java设计模式之共享模式/享元模式(Flyweight模式)介绍

    2023-06-15 04:35:10
  • java启动线程的3种方式对比分析

    2023-12-17 08:38:41
  • Java 导出Excel增加下拉框选项

    2021-10-13 07:58:50
  • 使用SharedPreferences在Android存储对象详细代码

    2022-06-14 12:50:29
  • SpringBoot2.1.4中的错误处理机制

    2023-11-06 02:48:47
  • Java中通过jsch来连接远程服务器执行linux命令

    2023-02-02 22:21:52
  • Java CompletableFuture实现多线程异步编排

    2023-07-22 22:57:02
  • SpringBoot统一响应格式及统一异常处理

    2022-08-30 08:03:08
  • Java毕业设计实战之在线蛋糕销售商城的实现

    2022-06-06 14:25:39
  • Android实现上下菜单双向滑动

    2023-06-10 02:43:37
  • Spring+SpringMVC+MyBatis深入学习及搭建(二)之MyBatis原始Dao开发和mapper代理开发

    2021-07-24 06:36:00
  • Spring Boot示例分析讲解自动化装配机制核心注解

    2022-07-26 15:56:14
  • java枚举类型-Enum

    2021-07-11 00:56:47
  • java文件读写工具类分享

    2023-07-30 21:04:19
  • Android中js和原生交互的示例代码

    2022-12-25 16:04:57
  • SpringMVC form标签引入及使用方法

    2023-02-16 17:58:41
  • Android手机抓包步骤

    2022-05-03 18:15:59
  • C# Random类的正确应用方法

    2021-06-25 14:56:17
  • listview控件实现点击列表头进行listview排序示例分享

    2023-06-06 18:00:39
  • android之BroadcastReceiver应用详解

    2021-08-31 16:05:21
  • asp之家 软件编程 m.aspxhome.com