自定义View等级滑动条的实现
package com.loaderman.beautyseekbarviewdemo; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView; public class MainActivity extends AppCompatActivity { private BeautySeekBarView beautySeekBarView;
private TextView mTextView; @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 BeautySeekBarView.indexListener() {
@Override
public void getIndex(int index) {
mTextView.setText("index="+index);
}
});
}
}
package com.loaderman.beautyseekbarviewdemo; 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; import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Semaphore; 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;
} }
activity-main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:ws="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#ccc"
tools:context="com.loaderman.beautyseekbarviewdemo.MainActivity"> <com.loaderman.beautyseekbarviewdemo.BeautySeekBarView
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_centerVertical="true"
ws:bigPic="@drawable/avatar_left"
ws:lineColor="#FFFFFF"
ws:padding="20dp"
ws:pointColor="#FFFFFF"
ws:smallPic="@drawable/number_bg"
ws:valueCountent="6"/> <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
自定义属性assets.xml
<?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>
效果图:
自定义View等级滑动条的实现的更多相关文章
- Android 自定义 View 圆形进度条总结
Android 自定义圆形进度条总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 微信公众号:牙锅子 源码:CircleProgress 文中如有纰漏,欢迎大家留言指出. 最近 ...
- Android开源中国客户端学习 (自定义View)左右滑动控件ScrollLayout
左右滑动的控件我们使用的也是非常多了,但是基本上都是使用的viewpager 等 android基础的控件,那么我们有么有考虑过查看他的源码进行定制呢?当然,如果你自我感觉非常好的话可以自己定制一个, ...
- 自定义View画一条线
#import "PublishContextView.h" @implementation PublishContextView -(void)drawRect:(CGRect) ...
- Android 自定义View合集
自定义控件学习 https://github.com/GcsSloop/AndroidNote/tree/master/CustomView 小良自定义控件合集 https://github.com/ ...
- android 开发 View _14 MotionEvent和事件处理详解,与实践自定义滑动条View
转载https://blog.csdn.net/huaxun66/article/details/52352469 MotionEvent MotionEvent对象是与用户触摸相关的时间序列,该序列 ...
- 自定义scrollview右侧的滑动条
在做这个功能之前我其实是拒绝的,为什么这么说呢,因为我怕麻烦啊!(开玩笑的,怕麻烦就不做程序员了) 很久没有写博客,这次刚好项目中有个有趣的东西,想拿出来分享一下,希望能帮到某些小伙伴. 首先说说需求 ...
- Android自定义View实战(SlideTab-可滑动的选择器)
转载请标明出处: http://blog.csdn.net/xmxkf/article/details/52178553 本文出自:[openXu的博客] 目录: 初步分析重写onDraw绘制 重写o ...
- Dialog详解(包括进度条、PopupWindow、自定义view、自定义样式的对话框)
Dialog详解(包括进度条.PopupWindow.自定义view.自定义样式的对话框) Android中提供了多种对话框,在实际应用中我们可能会需要修改这些已有的对话框.本实例就是从实际出发, ...
- Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)
Android 高手进阶(21) 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请注明地址:http://blog.csdn.net/xiaanming/article/detail ...
随机推荐
- wiki部署
一.准备环节 1.上传软件 [root@web01 tools]# tar xf jdk-8u60-linux-x64.tar.gz -C /application/ [root@web01 ...
- centos 7 私有云盘 OwnCloud 安装搭建脚本
#!/bin/bash #Build LAMP Server Conf mysql_secure_installation service mariadb restart systemctl enab ...
- Linux配置iSCSI存储
1.基础知识 1.1 存储相关 直接存储(DAS):例如本机上的磁盘,就是属于直接存储设备. 存储区域网络(SAN):来自网络内的其他存储设备提供的磁盘.Iscsi就是属于该方式. ...
- Zabbix报错:"Zabbix http poller processes more than 75% busy"的解决
一.钉钉收到告警 主机名称:Zabbix服务端-172.28.18.75 IP地址 :127.0.0.1 告警时间:2019.10.22 13:34:39 告警信息:Zabbix http polle ...
- PAT Basic 1005 继续(3n+1)猜想 (25 分)
卡拉兹(Callatz)猜想已经在1001中给出了描述.在这个题目里,情况稍微有些复杂. 当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数.例如对 n=3 进行验证的时 ...
- 自动化运维——MySQL备份脚本(二)
使用if语句编写MySQL备份脚本 代码: #!/bin/bash #auro backup mysql db #by steve yu #define backup path BAK_DIR=/da ...
- windows下遍历文件夹下的文件
#include <io.h>#include <stdio.h>#include <iostream>using namespace std;int ReadSt ...
- 在table中加入<hr />标签为什么横线会跑到上边?
这是我今天在写页面的时候发现的一个问题,万能的百度已经帮我找到答案啦!!!在此分享给你们吧 table>[caption|thead>tr|tbody>tr]>[th|td] ...
- 使用maven简单搭建Spring mvc + redis缓存
注:此文参考并整合了网上的文章 <spring缓存机制>:http://blog.csdn.net/sidongxue2/article/details/30516141 <配置 S ...
- DB2中常见sqlCode原因分析
000 | 00000 | SQL语句成功完成 01xxx | SQL语句成功完成,但是有警告 +012 | 01545 | 未限定的列名被解释为一个有相互关系的引用 +098 | 01568 | 动 ...