android 自定义view滚动条,Android自定义View实现等级滑动条的实例

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

实现效果图:

c3e85501693d4dd32541120afe87719a.gif

思路:

首先绘制直线,然后等分直线绘制点;

绘制点的时候把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);

}

});

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/550924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android短信验证码代码,Android短信验证码自动填写实现代码

今天给大家分享一个Android短信验证码自动填写的功能。先看下效果图&#xff0c;我发送了一条短信到手机&#xff0c;自动填写验证码。如图&#xff1a;这个小功能运用到了观察者模式&#xff0c;什么是观察者模式&#xff1f;观察者模式 &#xff1a;定义对象间的一种一个(Sub…

android 评论的展开功能,Android开发实现ListView点击展开收起效果示例

本文实例讲述了Android开发实现ListView点击展开收起效果。分享给大家供大家参考&#xff0c;具体如下&#xff1a;废话不说先上效果&#xff1a;实际上这是采用一个ExpandableListView实现的布局文件很简单&#xff1a;xmlns:android"http://schemas.android.com/apk/res…

画流程图activiti流程图_干货!小白也能一天画100张高逼格流程图

今天是在一起两周年零128天纪念日~你喜滋滋地订好了花&#xff0c;买好了酒&#xff0c;暗暗盘算着下班以后赶紧走~不料老板的命令从天而降“出100张流程图&#xff0c;今天给我&#xff01;”What&#xff1f;&#xff1f;&#xff1f;100张&#xff01;&#xff01;&#xff…

linux修图,修图只知道Photoshop?11款高逼格修图工具快来get!

精致的产品是在线商店成功的一个重要元素。虽然Adobe Photoshop长期以来一直是编辑图像的行业标准&#xff0c;但也有许多免费或廉价的应用程序和类似的工具。本文将为大家介绍一些Photoshop的替代品&#xff0c;包括在线应用程序和图形软件套件&#xff0c;它们都具有创建动态…

Android10打断动画,Android开发(10) 动画(Animation)

概述Android SDK介绍了两种Animation&#xff1a;Tween Animation&#xff1a;通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果&#xff0c;即是一种 渐变动画 &#xff0c;或者说 补间动画。Frame Animation&#xff1a;顺序播放事先做好的图像&#xff0c;是…

safari浏览器横屏怎么设置_如何避免苹果safari自带浏览器“跟踪”你的信息!

苹果自带的“safari浏览器”正在悄悄“追踪”你的信息&#xff0c;这样做可以有效避免你的隐私信息不被泄露。说起苹果设备自带的APP&#xff0c;毫无疑问safari浏览器是其中的代表之一&#xff0c;很多朋友由于习惯的原因&#xff0c;大多在使用苹果设备的时候选择下载一些第三…

自动提示_EXCEL2013版突然打不开,自动修复提示1907错误

由于系统升级或电脑进行修复操作&#xff0c;导致EXCEL突然打不开。office自动修复的时候提示错误1907。无法注册字体。请确认有足够的权限安装字体&#xff0c;并且系统支持此字体。解决方法一&#xff1a;直接点击忽略即可。一般点击一下忽略&#xff0c;它没有反应&#xff…

matlab去除图片水印_(水印去除技巧)3个在线图片水印去除网站,值得收藏

嗨&#xff01;大家好&#xff01;我是网罗小帅。很高兴和大家见面。今天是五一放假的第一天。有人说&#xff0c;新媒体人你不佩有五一假期。我太“南”了&#xff01;今天带来一波图片&#xff0c;视频去水印技巧干货神器。有时候我们看到一些漂亮的壁纸&#xff0c;但是别人…

android 软键盘遮住按钮,Android应用中出现软键盘遮挡住按钮如何解决

Android应用中出现软键盘遮挡住按钮如何解决发布时间&#xff1a;2020-11-20 16:25:47来源&#xff1a;亿速云阅读&#xff1a;110作者&#xff1a;LeahAndroid应用中出现软键盘遮挡住按钮如何解决&#xff1f;相信很多没有经验的人对此束手无策&#xff0c;为此本文总结了问题…

android底部弹出显示不全,Android 解决 NestedScrollView 底部内容被遮挡显示不全

Android 解决 NestedScrollView 底部内容被遮挡显示不全很早之前就遇到过在使用 NestedScrollView 的时候发现底部的 View 总是显示不全, 看起来像是被底部的什 padding 遮挡了一样.这次是一个 recycleView, 在 list 没有数据的时候总是显示不全, 有数据的时候就正常了. 子类控…

php调用python绘图程序_如何在matlab中调用python程序

现在python很火&#xff0c;很多代码都是python写的&#xff0c;如果你和我一样&#xff0c;习惯了使用matlab&#xff0c;还想在matlab中调用Python的代码&#xff0c;应该怎么办呢&#xff1f;其中一条思路&#xff1a;首先在matlab中调用系统脚本命令&#xff0c;然后再通过…

解释器android,Android的设计模式-解释器模式

前言Android的设计模式系列文章介绍&#xff0c;欢迎关注&#xff0c;持续更新中&#xff1a;1.定义给定一门语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。2.介绍解释器模式属于行为型模式。解释器模…

下载人脸认证助手_关于微信人脸解封验证失败方法

微信解封人脸验证失败&#xff01;我知道大家出现了这个问题。嗯&#xff0c;我也是前两天出现过的&#xff0c;前两天我一觉起来打开微信&#xff0c;发现自己的微信被封了。然后我就很着急的去解封。然后他就是让绑银行卡&#xff0c;然后进行实名认证之后进行人脸解封&#…

android照片如何查看时间,Android 获取照片时间

1、手机拍摄的照片(ExifInterface )ExifInterface exifInterface null;try {exifInterface new ExifInterface(oldPath);} catch (Exception e) {e.printStackTrace();}String watermarkTime exifInterface.getAttribute(ExifInterface.TAG_DATETIME);//ExifInterface方法只…

罗宾斯管理学13版pdf_全球著名管理学家,曾任五大高校教授,罗宾斯教你如何做好管理者...

在管理界&#xff0c;除了德鲁克能被称之为管理学大师&#xff0c;还有一位满腹经纶的管理学家&#xff0c;他就是斯蒂芬P罗宾斯&#xff0c;这位全球著名的管理学家&#xff0c;曾先后在布拉斯加大学、协和大学、巴尔的摩大学、南伊利诺伊大学、圣迭戈大学五大高校任教&#x…

img标签默认有外边距吗_你知道css的盒模型吗?

CSS盒子模型与怪异盒模型 盒子模型(Box Modle)可以用来对元素进行布局&#xff0c;包括内边距(padding)&#xff0c;边框(border)&#xff0c;外边距(margin)&#xff0c;和实际内容(content)这几个部分。标准盒模型 标准盒模型中盒子的大小是指&#xff1a;content border p…

js html 转换为富文本,如何将富文本得到的html转换为pdf?

问题描述我想将kindtor最后得到的html转换为pdf&#xff0c;有一种思路是将获得的html通过dom-to-image或者html2canvas转换为图片。在转换为pdf&#xff0c;但是我获得到html之后&#xff0c;运用dom-to-image转换或者html都不行&#xff0c;会报错出来。问题出现的环境背景及…

rust雪山矿洞几个入口_梅里雪山内转全记录(雨崩徒步:神湖神瀑冰湖)

头一次徒步完还愿意记录一下&#xff0c;两个原因吧&#xff1a;1&#xff09;出发前搜雨崩攻略&#xff0c;各大网站都很少有详细且完整的回答&#xff0c;2&#xff09;朋友圈发图后&#xff0c;好多朋友对雨崩有兴趣求攻略。先把此次行程大概列一下&#xff0c;如果还有兴趣…

微型计算机上的南桥芯片功能,微型计算机及接口技术2012年1月真题试题(04732)...

微型计算机及接口技术2012年1月真题试题及答案解析(04732)微型计算机及接口技术2012年1月真题试题及答案解析(04732)&#xff0c;本试卷总分100分。一、单项选择题(本大题共20小题&#xff0c;每小题1分&#xff0c;共20分)在每小题列出的四个备选项中只有一个是符合题目要求的…

空值用前值填充_用Excel进行数据处理

Excel是一款常用的办公软件&#xff0c;它的功能强大&#xff0c;本文我们将学习如何使用Excel 2019进行数据处理。导入数据本文使用的数据来自This Week’s Garbage Data File.xlsx。数据格式如上所示&#xff1a;表示销售日期表示销售人员名称和ID表示销售区域表示总计为了对…