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

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

实现效果图:

思路:

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

绘制点的时候把X值存到集合中。

然后绘制背景图片,以及图片上的数字。

点击事件down的时候,换小图片为大图片。move的时候跟随手指移动。

up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去。

1,自定义属性

<?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>

然后获取属性:

 /**
     * 获得我们所定义的自定义样式属性
     */
    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<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); //绘制文字
  }

全部代码如下

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<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;
  }

}

外部调用:

XML:

 <com.example.hello.BeautySeekBarView
    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);
    }
  });
  }

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

(0)

相关推荐

  • 解决Android SDK下载和更新失败的方法详解

    最近刚换了电脑,开始搭建Android开发环境的时候,下载SDK总是会出现如下错误: 复制代码 代码如下: Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-1.xml. 说dl-ssl.google.com在大陆被强了,解决方法就是修改C:\Windows\System32\drivers\etc\hosts文件.添加一行: 复制代码 代码如下: 74.125.237.1       dl-s

  • android listview优化几种写法详细介绍

    这篇文章只是总结下getView里面优化视图的几种写法,就像孔乙己写茴香豆的茴字的几种写法一样,高手勿喷,勿笑,只是拿出来分享,有错误的地方欢迎大家指正,谢谢. listview Aviewthatshowsitemsinaverticallyscrollinglist. 一个显示一个垂直的滚动子项的列表视图在android开发中,使用listview的地方很多,用它来展现数据,成一个垂直的视图.使用listview是一个标准的适配器模式,用数据--,界面--xml以及适配器--adapter,

  • Android的Activity跳转动画各种效果整理

    大家使用Android的原生UI都知道,Android的Activity跳转就是很生硬的切换界面.其实Android的Activity跳转可以设置各种动画.下面给大家看看效果:  实现非常简单,用overridePendingtransition(int inId, int outId)即可实现.inId是下一界面进入效果的xml文件的id,outId是当前界面退出效果的xml文件id. 效果是用xml文件写的,首先要在res文件夹下建立anim文件夹,然后把动画效果xml文件放到里面去. 下面

  • android调试工具DDMS的使用详解

    具体可见http://developer.android.com/tools/debugging/ddms.html. DDMS为IDE和emultor.真正的android设备架起来了一座桥梁.开发人员可以通过DDMS看到目标机器上运行的进程/现成状态,可以 android的屏幕到开发机上,可以看进程的heap信息,可以查看logcat信息,可以查看进程分配内存情况,可以像目标机发送短信以及打电话,可 以像android开发发送地理位置信息.可以像gdb一样attach某一个进程调试. SDK

  • Android SQLite数据库增删改查操作的使用详解

    一.使用嵌入式关系型SQLite数据库存储数据 在Android平台上,集成了一个嵌入式关系型数据库--SQLite,SQLite3支持NULL.INTEGER.REAL(浮点数字). TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上sqlite3也接受varchar(n). char(n).decimal(p,s) 等数据类型,只不过在运算或保存时会转成对应的五种数据类型. SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段

  • Android应用开发SharedPreferences存储数据的使用方法

    SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-value(键值对).SharedPreferences常用来存储一些轻量级的数据. 复制代码 代码如下: //实例化SharedPreferences对象(第一步) SharedPreferences mySharedPreferences= getSharedPreferences("test", Activity.MODE_PRIVATE);

  • android TextView设置中文字体加粗实现方法

    英文设置加粗可以在xml里面设置: 复制代码 代码如下: <SPAN style="FONT-SIZE: 18px">android:textStyle="bold"</SPAN> 英文还可以直接在String文件里面直接这样填写: 复制代码 代码如下: <string name="styled_text">Plain, <b>bold</b>, <i>italic</

  • Android Bitmap详细介绍

    复制代码 代码如下: package com.testbitmapscale; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import com.testbitmapscale.R.drawable; im

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

     Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候,换小图片为大图片.move的时候跟随手指移动. up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去. 1,自定义属性 <?xml version="1.0" encoding="utf-8"?> <resources> <de

  • Android自定义View实现左右滑动选择出生年份

    自定义view的第三篇,模仿的是微博运动界面的个人出生日期设置view,先看看我的效果图: 支持设置初始年份,左右滑动选择出生年份,对应的TextView的值也会改变.这个动画效果弄了好久,感觉还是比较生硬,与微博那个还是有点区别.大家有改进的方案,欢迎一起交流. 自定义View四部曲,这里依旧是这个套路,看看怎么实现的. 1.自定义view的属性: 在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性以及声明我们的整个样式. <?xml version="1.

  • Android自定义View实现圆环进度条

    本文实例为大家分享了Android自定义View实现圆环进度条的具体代码,供大家参考,具体内容如下 效果展示 动画效果 View实现 1.底层圆环是灰色背景 2.上层圆环是红色背景 3.使用动画画一条弧线 View /** * 圆环进度条 */ public class RoundProgressBar extends View { //绘制矩形区域 private RectF rectF; //起始角度 private float startAngle; //扫过角度 private floa

  • Android自定义View实现圆形进度条

    本文实例为大家分享了Android自定义View实现圆形进度条的具体代码,供大家参考,具体内容如下 效果如下: 主要代码 CircularProgressView.java public class CircularProgressView extends View { private Paint mBackPaint, mProgPaint; // 绘制画笔 private RectF mRectF; // 绘制区域 private int[] mColorArray; // 圆环渐变色 pr

  • Android自定义view实现圆环进度条效果

    本文实例为大家分享了Android自定义view实现圆环进度条效果的具体代码,供大家参考,具体内容如下 一.实现效果图 二.核心代码 自定义view的属性 <?xml version="1.0" encoding="utf-8"?> <resources>     <declare-styleable name="RingProgressBar">         <attr name="rin

  • Android中View跟随手指滑动效果的实例代码

    本文讲述了Android中View跟随手指滑动效果的实例代码.分享给大家供大家参考,具体如下: 1.android View 主要6种滑动方法,分别是 layout() offsetLeftAndRight()和offsetTopAndBottom() LayoutParams scrollBy()和 scrollTo() Scroller 动画 2.实现效果图 3.自定义中使用layout()方法实习view的滑动 public class MoveView extends View { pr

  • Android自定义View实现箭头沿圆转动实例代码

    具体代码如下所示: //MyCircleView类 public class MyCircleView extends View{ //当前画笔画圆的颜色 private int CurrenCircleBoundColor; private Paint paint; ////从xml中获取的颜色 private int circleBundColor; private float circleBoundWidth; private float pivotX; private float piv

  • Android自定义View之圆形进度条式按钮

    介绍 今天上班的时候有个哥们问我怎么去实现一个按钮式的进度条,先来看看他需要实现的效果图. 和普通的圆形进度条类似,只是中间的地方有两个状态表示,未开始,暂停状态.而且他说圆形进度的功能已经实现了.那么我们只需要对中间的两个状态做处理就行了. 先来看看实现的效果图: 上面说了我们只需要处理中间状态的变化就可以了,对于进度的处理直接使用了弘洋文章中实现: http://blog.csdn.net/lmj623565791/article/details/43371299 下面开始具体实现. 具体实

  • Android自定义View实现竖向滑动回弹效果

    本文实例为大家分享了Android自定义View实现滑动回弹的具体代码,供大家参考,具体内容如下 前言 Android 页面滑动的时候的回弹效果 一.关键代码 public class UniversalBounceView extends FrameLayout implements IPull {       private static final String TAG = "UniversalBounceView";     //default.     private sta

  • Android自定义View实现环形进度条的思路与实例

    前言 前段时间看到了豆瓣FM的音乐播放界面,有一个环形的进度条,非常的好看,于是想了想,为什么不自己做一个呢,于是就开始了自定义的过程 豆瓣FM的播放界面如下图: 功能分析 虽然功能比较简单,但是仍然需要仔细分析 1.图标外还有一圈圆圈,可以设置宽度 2.圆形进度条和进度条底部,可以设置宽度,颜色等 3.内部有一个圆形图片,可旋转 实现思路分析 1.可以设置宽度的圆圈 这个比较容易,直接在onDraw方法中使用canvas绘制即可,当然,在间距和半径的处理上需要仔细,控件本体其实还是一个长方形,

随机推荐