android 自定义view滚动条,Android自定义View实现等级滑动条的实例
Android自定义View实现等级滑动条的实例
实现效果图:
思路:
首先绘制直线,然后等分直线绘制点;
绘制点的时候把X值存到集合中。
然后绘制背景图片,以及图片上的数字。
点击事件down的时候,换小图片为大图片。move的时候跟随手指移动。
up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去。
1,自定义属性
然后获取属性:
/**
* 获得我们所定义的自定义样式属性
*/
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
PointX=i*averageLength+getPaddingLeft();
canvas.drawPoint(PointX, PointY, pointPaint);//绘制点
if(pointList!=null && pointList.size()
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 pointList;//储存画出的点的point值
private HashMap 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();
mHashMap=new HashMap();
}
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
PointX=i*averageLength+getPaddingLeft();
canvas.drawPoint(PointX, PointY, pointPaint);//绘制点
if(pointList!=null && pointList.size()
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:
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 自定义view滚动条,Android自定义View实现等级滑动条的实例相关推荐
- android 消息循环滚动条,Android ViewPager实现循环滚动
流量预警 内含三张4M+的GIF图片,流量慎入 转载请注明出处 以下图片来源于https://pixabay.com/ gif!图片外链服务由贴图库提供 画廊效果的部分来自博客园博主@阿呆哥哥的教程 ...
- android 设置listview滚动条,Android ListView 滚动条的设置详解及实例代码
Android ListView 滚动条的设置详解 1.滚动条的属性 android:scrollbarAlwaysDrawHorizontalTrack 设置是否始终显示水平滚动条.这里用Scrol ...
- android 禁止view滚动条,Android:禁止滚动的解决方法
这是纠结了我很久的一个问题,当我们在一个View里又嵌套一个View,但是两个View的内容超出范围后都会滚动的情况下,怎么保证内层的View固定不滚动. 一个Activity中有多个GridView ...
- android 垂直自动滚动条,Android实现Activity水平和垂直滚动条的方法
本文实例讲述了Android实现Activity水平和垂直滚动条的方法.分享给大家供大家参考,具体如下: android:layout_width="match_parent" a ...
- Android仿滴滴首页上拉,仿照滴滴打车底部滑动条
[实例简介] 仿照滴滴打车底部滑动条,代码详情 [实例截图] [核心代码] 仿滴滴打车滑动条 └── 仿滴滴打车滑动条 ├── AndroidManifest.xml ├── bin │ ├── ...
- android圆形点击效果,Android 三种方式实现自定义圆形页面加载中效果的进度条
[实例简介] Android 三种方式实现自定义圆形页面加载中效果的进度条 [实例截图] [核心代码] ad376a86-a9aa-49bc-8cea-321bcff2c0c3 └── AnimRou ...
- android布局的作用,Android UI布局经验总结
如何在Android中动态设置颜色透明?10%20%到100% Android布局分析工具HierarchyView Android使用include/merge/ViewStub优化布局 List的 ...
- Carson带你学Android:源码解析自定义View Draw过程
前言 自定义View是Android开发者必须了解的基础 网上有大量关于自定义View原理的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化 等 今天,我将全面总结自定义View ...
- Android进阶之光读书笔记——第三章:View体系与自定义View
第三章 View体系与自定义View 本章将介绍Android中十分重要的View,在多本书中View是必讲的一节,Android群英传就讲了不少的View的知识,那么在这里我们再去复习一遍吧 3.1 ...
最新文章
- SQL server 200 安装问题!
- 《算法竞赛进阶指南》打卡-基本算法-AcWing 99. 激光炸弹:二维前缀和
- JQuery-学习笔记04【基础——JQuery基础案例】
- 数据预处理:读取文件数据,并存为python数组
- ASP.NET会员注册登录模块(MD5加密,Parameters防止SQL注入,判断是否注册)
- php开发面试题---1、php常用面试题一(PHP有哪些特性)
- ASP.NET Web开发实用代码(一)
- 智能手机之新手篇[转]
- 剑指offer面试题04. 二维数组中的查找(Array)
- 项目介绍star原理_TiDB-Wasm 原理与实现 | Hackathon 优秀项目介绍
- 获取China大陆IP段的范围
- java制作qq自动回复,qq自动回复机器人-qq自动回复机器人 v1.6 电脑版
- Excel-数据透视表
- python动态调用函数
- 病毒性感冒和细菌性感冒怎样区分
- 基于Nodejs+vue开发实现高校学院网站系统
- 微信小程序 - 数据转excel下载并复制链接
- 什么是SDK什么是CDN
- 红米k30支持html,红米K30S至尊纪念版发布:骁龙865+支持144Hz高刷
- C语言那些事之标点符号
热门文章
- Oracle 10g、11g :RAC关闭、启动、重启步骤
- oracle 日志 LogMiner
- HSRP的初步解析及典型应用2
- [转]自定义SqlMembershipProvider方法
- 华为智能手环智能手表软件测试,一块智能手表的测试之旅,揭秘华为运动健康科学实验室...
- oracle中的(+)
- Android adb命令选择设备操作
- linux php任务计划,linux系统怎么添加计划任务执行php文件
- label qt 自动换行_QT编写一个登录界面
- 威纶通触摸屏与mysql_威纶触摸屏应用实例 以及威纶通触摸屏配方组合