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);
}
});
}
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
您可能感兴趣的文章:Android应用开发SharedPreferences存储数据的使用方法android TextView设置中文字体加粗实现方法android调试工具DDMS的使用详解Android Bitmap详细介绍Android的Activity跳转动画各种效果整理android listview优化几种写法详细介绍解决Android SDK下载和更新失败的方法详解Android SQLite数据库增删改查操作的使用详解