自定义拖拽IndicatorView
来源:互联网 发布:淘宝店铺粉丝最多 编辑:程序博客网 时间:2024/05/22 23:55
1. 效果图
2. 根据效果,定义需要属性:
其中模式下: 手动不可点击, 风速时: 最低和最高不可点击, 定时模式: 全部可以点击设置.
<declare-styleable name="IndicatorView"> <attr name="units" format="integer|reference"/> <attr name="lightColor" format="reference|color"/> <attr name="lightBitmap" format="reference"/> <attr name="indicators" format="reference|string"/> <attr name="controlStyle" format="enum"> <enum name="mode" value="0"/> <enum name="wind" value="1"/> <enum name="time" value="2"/> </attr> </declare-styleable>
private void parserAttrs(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView); mLightColor = ta.getColor(R.styleable.IndicatorView_lightColor, Color.argb(0xFF, 0xFF, 0xC1, 0x00)); int resourceId = ta.getResourceId(R.styleable.IndicatorView_lightBitmap, 0); mLightBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId); mText = ta.getString(R.styleable.IndicatorView_indicators); mIndicators = mText.split(","); mUnits = mText.split(",").length - 1; int mode = ta.getInt(R.styleable.IndicatorView_controlStyle, TIME); switch (mode) { case MODE: mType = MODE; break; case WIND: mType = WIND; break; case TIME: mType = TIME; break; } ta.recycle(); }
2. 初始化控件的一些默认值:
@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mLeftX = getPaddingLeft(); mAvailableWidth = w - getPaddingLeft() - getPaddingRight(); float unit = mAvailableWidth / mUnits; mThumbX = mLeftX + unit * mPosition;//粘近position}
3. 测量控件的宽高:
/*简单测量,只支持为match_parent或者固定值*/ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width; int height; final int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec); final int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec); final int measureWidth = MeasureSpec.getSize(widthMeasureSpec); final int measureHeight = MeasureSpec.getSize(heightMeasureSpec); /*布局width为match_parent或者固定值*/ if (measureWidthMode == MeasureSpec.EXACTLY) { width = measureWidth; } else { width = mDefaultWidth; } /*布局height为match_parent或者固定值*/ if (measureHeightMode == MeasureSpec.EXACTLY) { height = measureHeight; } else { height = mDefaultHeight; } setMeasuredDimension(width, height); }
4.绘制thumb, 文本,及其tracker
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawTrack(canvas); drawIndicatorTexts(canvas); drawThumb(canvas); } /** * 绘制thumb所在的track * * @param canvas */ private void drawTrack(Canvas canvas) { Rect rect = new Rect(mLeftX, getHeight() * 2 / 3 - mTrackHeight / 2, mLeftX + mAvailableWidth, getHeight() * 2 / 3 + mTrackHeight / 2); mPaint.setColor(Color.parseColor("#ededed")); canvas.drawRect(rect, mPaint); } /** * 绘制indicators * * @param canvas */ private void drawIndicatorTexts(Canvas canvas) { int count = mUnits; Paint paint; for (int i = 0; i <= count; i++) { final float x = mAvailableWidth / count * i + mLeftX; if (i == mPosition) {//当前选中的position paint = mTextPaint; mTextPaint.setColor(mLightColor); } else {//没选中的position paint = mTextPaint; mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB)); } paint.getTextBounds(mIndicators[i], 0, mIndicators[i].length(), mTextRect); String text = mIndicators[i]; canvas.drawText(text, x - mTextRect.width() / 2, getHeight() / 3, paint); } } /** * 绘制thumb * * @param canvas */ private void drawThumb(Canvas canvas) { Bitmap bitmap = mLightBitmap; mThumbX = getThumbX(mPosition); if (bitmap != null) { canvas.drawBitmap(bitmap, mThumbX - bitmap.getWidth() / 2, getHeight() * 2 / 3 - bitmap.getHeight() / 2, null); } }
5. 构建点击事件的监听器:
@Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: { this.getParent().requestDisallowInterceptTouchEvent(true); float x = event.getX(); moveThumb(x); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { if (mListener != null) { mListener.onPositionChange(mPosition); } float x = event.getX(); moveThumb(x); this.getParent().requestDisallowInterceptTouchEvent(false); break; } } return true; } private void moveThumb(float x) { if (mPosition == getPosition(x)) { return; } mPosition = getPosition(x); switch (mType) { case MODE: if (mPosition == 0) { mPosition = 1; } break; case WIND: if (mPosition == 0) { mPosition = 1; } else if (mPosition == 4) { mPosition = 3; } break; case TIME: break; } mThumbX = getThumbX(mPosition); invalidate(); } /** * 根据thumb的坐标获取thumb的位置 * * @param x * @return */ private int getPosition(float x) { float unitWidth = mAvailableWidth / mUnits; float originX = (x - mLeftX + unitWidth / 2f) / unitWidth; return (int) originX; } /** * 根据thumb的位置获取thumb的坐标 * * @param position * @return */ private float getThumbX(int position) { float unit = mAvailableWidth / mUnits; return mLeftX + unit * position; }
6.保存与恢复自定义view的状态信息:
在屏幕旋转等情况要保存view的状态, 防止一些状态信息丢失,如thumb图标消失.
@Override protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof Bundle)) { super.onRestoreInstanceState(state); return; } Bundle bundle = (Bundle) state; mLightBitmap = bundle.getParcelable("bitmap"); mText = bundle.getString("indicators"); mPosition = bundle.getInt("position"); mThumbX = bundle.getFloat("thumbX"); mType = bundle.getInt("mType"); mTrackHeight = bundle.getInt("trackHeight"); super.onRestoreInstanceState(bundle.getParcelable("instance")); } //##### 对外公布的方法###########################// @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable("bitmap", mLightBitmap); bundle.putInt("position", mPosition); bundle.putString("indicators", mText); bundle.putFloat("thumbX", mThumbX); bundle.putInt("mType", mType); bundle.putInt("trackHeight", mTrackHeight); bundle.putParcelable("instance", super.onSaveInstanceState()); return bundle; }
完整代码:
package ****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.Rect;import android.os.Bundle;import android.os.Parcelable;import android.text.TextPaint;import android.util.AttributeSet;import android.util.TypedValue;import android.view.MotionEvent;import android.view.View;import com.bugull.yft_airclean.R;/** * @ author: showdy * @ time: 2016/5/21 14:20 * @ des: 用于控件界面的indicatorView */public class IndicatorView extends View { private static final int MODE = 0; private static final int WIND = 1; private static final int TIME = 2; private OnPositionChangedListener mListener; private int mUnits; private int mLightColor; private Bitmap mLightBitmap; private String mText; private Paint mPaint; private Paint mTextPaint; //文字画笔 private int mDefaultWidth; private int mDefaultHeight; private int mLeftX; private int mAvailableWidth; private float mThumbX; //thumb的起始横坐标 private int mPosition = 0; //当前位置 private String[] mIndicators; private Rect mTextRect; private int mTrackHeight = 0; private int mType = TIME; private Context mContext; public IndicatorView(Context context) { this(context, null); } public IndicatorView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public IndicatorView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; mTrackHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, context.getResources().getDisplayMetrics()); mDefaultWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 260, context.getResources().getDisplayMetrics()); mDefaultHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, context.getResources().getDisplayMetrics()); parserAttrs(context, attrs); initPaint(); } private void initPaint() { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB)); mPaint.setStyle(Paint.Style.FILL); mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB)); mTextPaint.setStyle(Paint.Style.FILL); mTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, getResources().getDisplayMetrics())); mTextRect = new Rect(); } private void parserAttrs(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndicatorView); mLightColor = ta.getColor(R.styleable.IndicatorView_lightColor, Color.argb(0xFF, 0xFF, 0xC1, 0x00)); int resourceId = ta.getResourceId(R.styleable.IndicatorView_lightBitmap, 0); mLightBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId); mText = ta.getString(R.styleable.IndicatorView_indicators); mIndicators = mText.split(","); mUnits = mText.split(",").length - 1; int mode = ta.getInt(R.styleable.IndicatorView_controlStyle, TIME); switch (mode) { case MODE: mType = MODE; break; case WIND: mType = WIND; break; case TIME: mType = TIME; break; } ta.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width; int height; final int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec); final int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec); final int measureWidth = MeasureSpec.getSize(widthMeasureSpec); final int measureHeight = MeasureSpec.getSize(heightMeasureSpec); if (measureWidthMode == MeasureSpec.EXACTLY) { width = measureWidth; } else { width = mDefaultWidth; } if (measureHeightMode == MeasureSpec.EXACTLY) { height = measureHeight; } else { height = mDefaultHeight; } setMeasuredDimension(width, height); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mLeftX = getPaddingLeft(); mAvailableWidth = w - getPaddingLeft() - getPaddingRight(); float unit = mAvailableWidth / mUnits; mThumbX = mLeftX + unit * mPosition;//粘近position } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnabled()) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: { this.getParent().requestDisallowInterceptTouchEvent(true); float x = event.getX(); moveThumb(x); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { if (mListener != null) { mListener.onPositionChange(mPosition); } float x = event.getX(); moveThumb(x); this.getParent().requestDisallowInterceptTouchEvent(false); break; } } return true; } private void moveThumb(float x) { if (mPosition == getPosition(x)) { return; } mPosition = getPosition(x); switch (mType) { case MODE: if (mPosition == 0) { mPosition = 1; } break; case WIND: if (mPosition == 0) { mPosition = 1; } else if (mPosition == 4) { mPosition = 3; } break; case TIME: break; } mThumbX = getThumbX(mPosition); invalidate(); } /** * 根据thumb的坐标获取thumb的位置 * * @param x * @return */ private int getPosition(float x) { float unitWidth = mAvailableWidth / mUnits; float originX = (x - mLeftX + unitWidth / 2f) / unitWidth; return (int) originX; } /** * 根据thumb的位置获取thumb的坐标 * * @param position * @return */ private float getThumbX(int position) { float unit = mAvailableWidth / mUnits; return mLeftX + unit * position; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawTrack(canvas); drawIndicatorTexts(canvas); drawThumb(canvas); } /** * 绘制thumb所在的track * * @param canvas */ private void drawTrack(Canvas canvas) { Rect rect = new Rect(mLeftX, getHeight() * 2 / 3 - mTrackHeight / 2, mLeftX + mAvailableWidth, getHeight() * 2 / 3 + mTrackHeight / 2); mPaint.setColor(Color.parseColor("#ededed")); canvas.drawRect(rect, mPaint); } /** * 绘制indicators * * @param canvas */ private void drawIndicatorTexts(Canvas canvas) { int count = mUnits; Paint paint; for (int i = 0; i <= count; i++) { final float x = mAvailableWidth / count * i + mLeftX; if (i == mPosition) {//当前选中的position paint = mTextPaint; mTextPaint.setColor(mLightColor); } else {//没选中的position paint = mTextPaint; mTextPaint.setColor(Color.argb(0xFF, 0xBB, 0xBB, 0xBB)); } paint.getTextBounds(mIndicators[i], 0, mIndicators[i].length(), mTextRect); String text = mIndicators[i]; canvas.drawText(text, x - mTextRect.width() / 2, getHeight() / 3, paint); } } /** * 绘制thumb * * @param canvas */ private void drawThumb(Canvas canvas) { Bitmap bitmap = mLightBitmap; mThumbX = getThumbX(mPosition); if (bitmap != null) { canvas.drawBitmap(bitmap, mThumbX - bitmap.getWidth() / 2, getHeight() * 2 / 3 - bitmap.getHeight() / 2, null); } } @Override protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof Bundle)) { super.onRestoreInstanceState(state); return; } Bundle bundle = (Bundle) state; mLightBitmap = bundle.getParcelable("bitmap"); mText = bundle.getString("indicators"); mPosition = bundle.getInt("position"); mThumbX = bundle.getFloat("thumbX"); mType = bundle.getInt("mType"); mTrackHeight = bundle.getInt("trackHeight"); super.onRestoreInstanceState(bundle.getParcelable("instance")); } //##### 对外公布的方法###########################// @Override protected Parcelable onSaveInstanceState() { Bundle bundle = new Bundle(); bundle.putParcelable("bitmap", mLightBitmap); bundle.putInt("position", mPosition); bundle.putString("indicators", mText); bundle.putFloat("thumbX", mThumbX); bundle.putInt("mType", mType); bundle.putInt("trackHeight", mTrackHeight); bundle.putParcelable("instance", super.onSaveInstanceState()); return bundle; } public void setPosition(int position) { mPosition = position; invalidate(); } public void setLightColor(Context context, int resId, int color) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId); mLightBitmap = bitmap; mLightColor = color; invalidate(); } public void setOnPositionChangedListener(OnPositionChangedListener listener) { mListener = listener; } @Override public void setEnabled(boolean enabled) { if (!enabled) { setPosition(0); setLightColor(mContext, R.mipmap.fsk_thumb_black, Color.parseColor("#bbbbbb")); } super.setEnabled(enabled); } public interface OnPositionChangedListener { void onPositionChange(int position); }}
0 0
- 自定义拖拽IndicatorView
- Android自定义控件实现导航条IndicatorView
- Android自定义View之 实现一个多功能的IndicatorView
- Android自定义View之IndicatorView,显示当前tab页所处位置的View
- 新手CrossApp 之IndicatorView小结
- ios中为耗时动作添加indicatorview不可见问题及解决
- 自定义拖拽cell
- 页面自定义拖拽布局
- 页面自定义拖拽布局
- JS自定义拖拽setCapture
- 自定义拖拽布局,gridlayout
- 自定义alert(支持拖拽)
- 自定义Jquery拖拽插件
- 页面自定义拖拽布局,学习,研究
- 仿google自定义拖拽布局
- 仿iGoogle自定义首页模块拖拽
- Jquery.Sorttable 桌面拖拽自定义
- Jquery.Sorttable 桌面拖拽自定义
- LeetCode Swap Nodes in Pairs
- dataset总结
- 链接和库
- ListView的点击事件应用
- Batch Normalization导读
- 自定义拖拽IndicatorView
- post发送JSON数据(字符串、数组、字典、自定义对象)给服务器
- 手把手教你开发基于深度学习的人脸识别【考勤/签到】系统
- EditTexts实现图文混排
- Tomcat7.0源码分析——启动与停止服务原理
- netlink socket编程实例
- 串口通信中的float型数据的处理
- git
- linux下实现一个进度条