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


    package com.loaderman.beautyseekbarviewdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        private BeautySeekBarView beautySeekBarView;
        private TextView mTextView;
    
        @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 BeautySeekBarView.indexListener() {
                @Override
                public void getIndex(int index) {
                    mTextView.setText("index="+index);
                }
            });
        }
    }
    
    package com.loaderman.beautyseekbarviewdemo;
    
    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;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.concurrent.Semaphore;
    
    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;
        }
    
    }
    

     activity-main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:ws="http://schemas.android.com/apk/res-auto"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#ccc"
        tools:context="com.loaderman.beautyseekbarviewdemo.MainActivity">
    
        <com.loaderman.beautyseekbarviewdemo.BeautySeekBarView
            android:id="@+id/myView"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:layout_centerVertical="true"
            ws:bigPic="@drawable/avatar_left"
            ws:lineColor="#FFFFFF"
            ws:padding="20dp"
            ws:pointColor="#FFFFFF"
            ws:smallPic="@drawable/number_bg"
            ws:valueCountent="6"/>
    
        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
    

    自定义属性assets.xml

    <?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>
    

     效果图:

  • 相关阅读:
    git常用命令图解 & 常见错误
    关于ES6的Promise的使用深入理解
    几种简单排序算法代码
    HttpMessageNotWritableException异常解决办法
    关于 java swing 使用按钮关闭窗口
    几种简单的排序总结
    MJ老师博客园的美化代码
    [转]iOS开发之常用的数学函数和常数
    iOS如何简单实现绘制爱心?
    重新入门python爬虫到放弃
  • 原文地址:https://www.cnblogs.com/loaderman/p/6607802.html
Copyright © 2020-2023  润新知