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,一经查实,立即删除!

相关文章

二项分布的期望方差证明_关于二项分布

2007-01-07二项分布和正态分布的期望与方差EXn我介绍一个较繁但易懂的方法。先证kC(n,k)*p^k*q^(n-k)np*[C(n-1,k-1)*p^(k-1)q^(n-k)]过程如下&#xff1a;kC(n,k)*p^k*q^(n-k)k*(n!/[(n-k)!k!])*p^k*q^(n-k)np*[(n-1)!/((n-k)!(k-1)!]*p^(k-1)*q^(n-k)np*[C(n-1,k-1)*p^(k-1)q…

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

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

decimal类型 go_Go 语言程序设计——字符串类型(2)

格式化布尔值布尔值使用 %t (真值) 格式指令来输出例子&#xff1a;package mainimport ("fmt")func IntForBool (b bool) int {if b {return 1}return 0}func main() {fmt.Printf("%t %t\n", true, false)fmt.Printf("%d %d\n", IntForBool(tru…

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;它们都具有创建动态…

摆的频率公式_频率与转速的公式

信息举报时间&#xff1a;2020-12-24 本页为您甄选多篇描写频率与转速的公式,频率与转速的公式精选,频率与转速的公式大全&#xff0c;有议论&#xff0c;叙事 &#xff0c;想象等形式。文章字数有400字、600字、800字....想做一个lc振荡电路产生正弦波到方波产生电路形成一个方…

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;大多在使用苹果设备的时候选择下载一些第三…

android按钮旋转,单击一个按钮在android中顺时针旋转图像

我有一个要求,我有一个ImageView和一个按钮.我想在单击按钮时旋转图像.我需要全屏图像.但是当我点击按钮图像时会旋转,但不会在全屏显示.请参阅以下链接.之后,当我点击按钮图像时也会旋转.但是位置已更改且未全屏显示.我的要求是,当我点击按钮时,图像将顺时针旋转,并将全屏显示…

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

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

android 按钮改变顺序,在Android中定义RelativeLayout的Z视图顺序

在Android中定义RelativeLayout的Z视图顺序我想在Android中定义RelativeLayout视图的z顺序。我知道这样做的一种方法是拨打bringToFront。有更好的方法吗&#xff1f; 如果我可以在布局xml中定义z顺序会很棒。11个解决方案288 votes最简单的方法是简单地关注视图添加到XML文件的…

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;为此本文总结了问题…

python是开源工具吗_微软最强 Python 自动化工具开源了!不用写一行代码

1. 前言最近&#xff0c;微软开源了一款非常强大的 Python 自动化依赖库&#xff1a;playwright-python&#xff0c;它支持主流的浏览器&#xff0c;包含&#xff1a;Chrome、Firefox、Safari、Microsoft Edge 等&#xff0c;同时支持以无头模式、有头模式运行&#xff0c;play…

android 振动传感器,Android光线传感器

Android光线传感器[编辑]概述光线传感器&#xff0c;即光电感应器&#xff0c;将收到之光线讯号转变成电器信号&#xff0c;此电信讯号更可进一步作各种不同的开关及控制动作。一、简介目前智能手机上用光线传感器来调节屏幕明暗&#xff0c;就是在光线强的地方手机会自动关掉键…

tcp unity 图片_Unity 简易聊天室(基于TCP)(2)

客户端用Unity开发&#xff0c;主要就是搭建一下聊天室的UI界面&#xff1a;输入框&#xff0c;聊天内容显示框&#xff0c;发送按钮灰色背景的就是Message&#xff0c;也就是聊天内容的显示框&#xff0c;是一个Text类型&#xff0c;这里创建UI方面就不多讲了在Canvas下挂一个…

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.介绍解释器模式属于行为型模式。解释器模…