Android自定义控件之ToggleButton
来源:互联网 发布:睡眠时间 知乎 编辑:程序博客网 时间:2024/05/17 03:08
View的绘制流程
measure(): 测量,用来控制控件的大小,final 不建议复写
layout(): 布局,用来控制控件摆放的位置
draw(): 绘制,用来控制控件的样子
如果需要自定义view
onMeasure():
onLayout():
onDraw():
行为控制:(触摸)
dispatchTouchEvent(): (View和ViewGroup)分发touch,android希望开发者在这个方法中实现touch的传递
onInterceptTouchEvent(): (ViewGroup) 拦截touch事件,android希望开发者在这个方法中通过父容器来控制是否拦截孩子的touch
onTouchEvent(): (View和ViewGroup) 当用户触摸控件时候的回调,Android希望开发者在这个方法中实现行为
view.setOnTouchListener();
View的绘制刷新: invalidate()触发view的刷新–>draw()—>onDraw()
View的布局刷新 requestLayout()触发重新布局–>layout()—>onLayout()–>draw()—>onDraw()
public class SlideToggleView extends View { private final static int STATE_DOWN = 0; private final static int STATE_MOVE = 1; private final static int STATE_UP = 2; private Bitmap mBackground;// 滑动的背景 private Bitmap mSlideImage;// 滑动块的图片 private Paint paint = new Paint(); private boolean isOpened = false;// 用来标记控件是否是打开的 private float mCurrentX; private int mState = STATE_UP;// 用来记录用户当前手势的状态,默认状态 private OnToggleListener mListener; public SlideToggleView(Context context) { this(context, null); } public SlideToggleView(Context context, AttributeSet attrs) { super(context, attrs); } public void setSlideBackground(int resId) { mBackground = BitmapFactory.decodeResource(getResources(), resId); } public void setSlideImage(int resId) { mSlideImage = BitmapFactory.decodeResource(getResources(), resId); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 设置 当前控件的实际的宽高 if (mBackground != null) { int measuredWidth = mBackground.getWidth(); int measuredHeight = mBackground.getHeight(); setMeasuredDimension(measuredWidth, measuredHeight); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } @Override protected void onDraw(Canvas canvas) { // 画背景 if (mBackground != null) { // canvas 画布,画板 int left = 0; int top = 0; canvas.drawBitmap(mBackground, left, top, paint); } // 画滑动块 if (mSlideImage == null) { return; } // 当控件在左侧-->关闭情况 // 如果用户手指按下时,当前的点的水平坐标在 滑动块的左侧,就不动 // canvas.drawBitmap(mSlideImage, 0, 0, paint); int slideWidth = mSlideImage.getWidth(); int backWidth = mBackground.getWidth(); switch (mState) { case STATE_DOWN: case STATE_MOVE: if (!isOpened) { // 当控件在左侧-->关闭情况 if (mCurrentX < slideWidth / 2f) {// 当前的点的水平坐标在 滑动块的左侧 canvas.drawBitmap(mSlideImage, 0, 0, paint); } else { // 在右侧 float left = mCurrentX - slideWidth / 2f; float maxLeft = backWidth - slideWidth; if (left > maxLeft) { left = maxLeft; } canvas.drawBitmap(mSlideImage, left, 0, paint); } } else { // 在右侧--》打开的 // 当前的点的水平坐标在 滑动块的右侧,不动 if (mCurrentX > backWidth - slideWidth / 2f) { // 画打开的状态 float left = backWidth - slideWidth; canvas.drawBitmap(mSlideImage, left, 0, paint); } else { // float left = mCurrentX - slideWidth / 2f; if (left < 0) { left = 0; } canvas.drawBitmap(mSlideImage, left, 0, paint); } } break; case STATE_UP: if (isOpened) { // 打开的 float left = backWidth - slideWidth; canvas.drawBitmap(mSlideImage, left, 0, paint); } else { // 关闭的 canvas.drawBitmap(mSlideImage, 0, 0, paint); } break; default: break; } } @Override public boolean onTouchEvent(MotionEvent event) { // MotionEvent--->用户触摸时的实时数据 int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // 按下时 // 改变状态 mState = STATE_DOWN; mCurrentX = event.getX(); break; case MotionEvent.ACTION_MOVE: // 移动 mState = STATE_MOVE; mCurrentX = event.getX(); break; case MotionEvent.ACTION_UP: // 手指抬起 mState = STATE_UP; mCurrentX = event.getX(); int width = mBackground.getWidth(); if (mCurrentX > width / 2f && !isOpened) { // 打开 isOpened = true; if (mListener != null) { mListener.onToggleChanged(this, true); } } else if (mCurrentX <= width / 2f && isOpened) { // 关闭 isOpened = false; if (mListener != null) { mListener.onToggleChanged(this, false); } } break; default: break; } invalidate(); // 是否出处理touch事件 return true;// 消费掉所有的touch行为 } public void setOnToggleListener(OnToggleListener listener) { this.mListener = listener; } public interface OnToggleListener { // 暴露当前是否是打开或是关闭的状态,提供数据给调用者 void onToggleChanged(SlideToggleView view, boolean isOpened); }}
public class MainActivity extends Activity { private SlideToggleView mToggleView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mToggleView = (SlideToggleView) findViewById(R.id.stv); // 设置资源 mToggleView.setSlideBackground(R.drawable.switch_background); mToggleView.setSlideImage(R.drawable.slide_button_background); mToggleView.setOnToggleListener(new OnToggleListener() { public void onToggleChanged(SlideToggleView view, boolean isOpened) { Toast.makeText(MainActivity.this, isOpened ? "打开" : "关闭", Toast.LENGTH_SHORT).show(); } }); }}
参考:Android自定义控件
阅读全文
0 0
- Android自定义控件之ToggleButton
- android控件之ToggleButton
- Android控件之ToggleButton
- Android控件之ToggleButton
- Android控件之ToggleButton
- Android应用之——自定义控件ToggleButton
- Android 控件开发之ToggleButton
- Android控件之ToggleButton探究
- android开发之ToggleButton控件
- Android 控件开发之ToggleButton
- Android控件之ToggleButton、Switch
- Android系列控件之ToggleButton
- Android ToggleButton(自定义可滑动的ToggleButton控件)
- 自定义控件之仿IOS的ToggleButton
- 自定义控件之仿IOS的ToggleButton
- 自定义控件-仿iphone之ToggleButton&VoiceSeekBar
- 自定义ToggleButton选择控件
- Android控件开发之ToggleButton原理
- Android线程管理(二)——ActivityThread
- 6月27日云栖精选夜读:细数智能家居的痛点
- SVN中tag branch trunk用法详解
- 分析vivi.c
- redis事务处理
- Android自定义控件之ToggleButton
- 红黑树
- Photoshop简单几步搞定人物磨皮-非插件版
- 虚继承与虚基类的本质(介绍的非常详细)
- Android不编译某个模块
- linux下安装php的imagick扩展模块(附php升级脚本)
- 设计模式之结构型-桥接模式(10)
- python+HMM之维特比解码
- Android图片缓存之Glide进阶