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实现等级滑动条的实例相关推荐

  1. android 消息循环滚动条,Android ViewPager实现循环滚动

    流量预警 内含三张4M+的GIF图片,流量慎入 转载请注明出处 以下图片来源于https://pixabay.com/ gif!图片外链服务由贴图库提供 画廊效果的部分来自博客园博主@阿呆哥哥的教程 ...

  2. android 设置listview滚动条,Android ListView 滚动条的设置详解及实例代码

    Android ListView 滚动条的设置详解 1.滚动条的属性 android:scrollbarAlwaysDrawHorizontalTrack 设置是否始终显示水平滚动条.这里用Scrol ...

  3. android 禁止view滚动条,Android:禁止滚动的解决方法

    这是纠结了我很久的一个问题,当我们在一个View里又嵌套一个View,但是两个View的内容超出范围后都会滚动的情况下,怎么保证内层的View固定不滚动. 一个Activity中有多个GridView ...

  4. android 垂直自动滚动条,Android实现Activity水平和垂直滚动条的方法

    本文实例讲述了Android实现Activity水平和垂直滚动条的方法.分享给大家供大家参考,具体如下: android:layout_width="match_parent" a ...

  5. Android仿滴滴首页上拉,仿照滴滴打车底部滑动条

    [实例简介] 仿照滴滴打车底部滑动条,代码详情 [实例截图] [核心代码] 仿滴滴打车滑动条 └── 仿滴滴打车滑动条 ├── AndroidManifest.xml ├── bin │   ├── ...

  6. android圆形点击效果,Android 三种方式实现自定义圆形页面加载中效果的进度条

    [实例简介] Android 三种方式实现自定义圆形页面加载中效果的进度条 [实例截图] [核心代码] ad376a86-a9aa-49bc-8cea-321bcff2c0c3 └── AnimRou ...

  7. android布局的作用,Android UI布局经验总结

    如何在Android中动态设置颜色透明?10%20%到100% Android布局分析工具HierarchyView Android使用include/merge/ViewStub优化布局 List的 ...

  8. Carson带你学Android:源码解析自定义View Draw过程

    前言 自定义View是Android开发者必须了解的基础 网上有大量关于自定义View原理的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化 等 今天,我将全面总结自定义View ...

  9. Android进阶之光读书笔记——第三章:View体系与自定义View

    第三章 View体系与自定义View 本章将介绍Android中十分重要的View,在多本书中View是必讲的一节,Android群英传就讲了不少的View的知识,那么在这里我们再去复习一遍吧 3.1 ...

最新文章

  1. SQL server 200 安装问题!
  2. 《算法竞赛进阶指南》打卡-基本算法-AcWing 99. 激光炸弹:二维前缀和
  3. JQuery-学习笔记04【基础——JQuery基础案例】
  4. 数据预处理:读取文件数据,并存为python数组
  5. ASP.NET会员注册登录模块(MD5加密,Parameters防止SQL注入,判断是否注册)
  6. php开发面试题---1、php常用面试题一(PHP有哪些特性)
  7. ASP.NET Web开发实用代码(一)
  8. 智能手机之新手篇[转]
  9. 剑指offer面试题04. 二维数组中的查找(Array)
  10. 项目介绍star原理_TiDB-Wasm 原理与实现 | Hackathon 优秀项目介绍
  11. 获取China大陆IP段的范围
  12. java制作qq自动回复,qq自动回复机器人-qq自动回复机器人 v1.6 电脑版
  13. Excel-数据透视表
  14. python动态调用函数
  15. 病毒性感冒和细菌性感冒怎样区分
  16. 基于Nodejs+vue开发实现高校学院网站系统
  17. 微信小程序 - 数据转excel下载并复制链接
  18. 什么是SDK什么是CDN
  19. 红米k30支持html,红米K30S至尊纪念版发布:骁龙865+支持144Hz高刷
  20. C语言那些事之标点符号

热门文章

  1. Oracle 10g、11g :RAC关闭、启动、重启步骤
  2. oracle 日志 LogMiner
  3. HSRP的初步解析及典型应用2
  4. [转]自定义SqlMembershipProvider方法
  5. 华为智能手环智能手表软件测试,一块智能手表的测试之旅,揭秘华为运动健康科学实验室...
  6. oracle中的(+)
  7. Android adb命令选择设备操作
  8. linux php任务计划,linux系统怎么添加计划任务执行php文件
  9. label qt 自动换行_QT编写一个登录界面
  10. 威纶通触摸屏与mysql_威纶触摸屏应用实例 以及威纶通触摸屏配方组合