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
# 等级滑动条的实现
# Android自定义View实现滑动条
# Android应用开发SharedPreferences存储数据的使用方法
# android TextView设置中文字体加粗实现方法
# android调试工具DDMS的使用详解
# Android Bitmap详细介绍
# Android的Activity跳转动画各种效果整理
# android listview优化几种写法详细介绍
# 解决Android SDK下载和更新失败的方法详解
# Android SQLite数据库增删改查操作的使用详解
# 自定义
# 拖动
# 按下
# 过大
# 键值
# 过程中
# 后期
# 信号量
# 大图片
# 希望能
# 谢谢大家
# 画出
# 回调
# 为大
# getPaddingLeft
# getWidth
# linePaint
# getPaddingRight
# averageLength
# amp
相关文章:
宁波自助建站系统如何快速打造专业企业网站?
如何高效生成建站之星成品网站源码?
在线制作视频网站免费,都有哪些好的动漫网站?
网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
平台云上自助建站如何快速打造专业网站?
建站之星后台管理系统如何操作?
网站微信制作软件,如何制作微信链接?
如何通过虚拟主机快速搭建个人网站?
如何在阿里云ECS服务器部署织梦CMS网站?
学校建站服务器如何选型才能满足性能需求?
如何确保FTP站点访问权限与数据传输安全?
微信h5制作网站有哪些,免费微信H5页面制作工具?
IOS倒计时设置UIButton标题title的抖动问题
建站为何优先选择香港服务器?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
建站主机CVM配置优化、SEO策略与性能提升指南
如何在宝塔面板中修改默认建站目录?
威客平台建站流程解析:高效搭建教程与设计优化方案
建站一年半SEO优化实战指南:核心词挖掘与长尾流量提升策略
建站主机类型有哪些?如何正确选型
网站制作公司广州有几家,广州尚艺美发学校网站是多少?
免费ppt制作网站,有没有值得推荐的免费PPT网站?
建站之星伪静态规则如何正确配置?
如何在阿里云完成域名注册与建站?
网站制作公司排行榜,四大门户网站排名?
C#如何在一个XML文件中查找并替换文本内容
小米网站链接制作教程,请问miui新增网页链接调用服务有什么用啊?
建站之星展会模版如何一键下载生成?
网站制作公司排行榜,抖音怎样做个人官方网站
建站三合一如何选?哪家性价比更高?
高端网站建设与定制开发一站式解决方案 中企动力
建站之星北京办公室:智能建站系统与小程序生成方案解析
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
建站之星图片链接生成指南:自助建站与智能设计教程
郑州企业网站制作公司,郑州招聘网站有哪些?
如何选择CMS系统实现快速建站与SEO优化?
如何通过VPS建站无需域名直接访问?
宝塔面板创建网站无法访问?如何快速排查修复?
如何在万网主机上快速搭建网站?
如何做静态网页,sublimetext3.0制作静态网页?
想学网站制作怎么学,建立一个网站要花费多少?
如何用wdcp快速搭建高效网站?
如何基于PHP生成高效IDC网络公司建站源码?
在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?
内网网站制作软件,内网的网站如何发布到外网?
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
重庆市网站制作公司,重庆招聘网站哪个好?
*请认真填写需求信息,我们会在24小时内与您取得联系。