标签:state attr nullable prot Dimension content bre oid 移动
开关案例
public ToggleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); tbg = BitmapFactory.decodeResource(getResources(), R.drawable.toogle_background); sbg = BitmapFactory.decodeResource(getResources(), R.drawable.toogle_slidebg); slideMax = tbg.getWidth() - sbg.getWidth(); String namespace = "http://schemas.android.com/apk/res-auto"; boolean isOpen = attrs.getAttributeBooleanValue(namespace, "state", false); setOpenState(isOpen); if (state) { toLeft = slideMax; } else { toLeft = 0; } }
[2]重写onMeasure方法对当前view进行测量 当前view的宽高和toogleBg 一样
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(tbg.getWidth(), tbg.getHeight()); }
[3]重写onDraw方法往当前的view上画内容 其实就是画图片
@Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(tbg, 0, 0, null); canvas.drawBitmap(sbg, toLeft, 0, null); if (isUp) { isUp = false; boolean isOpenTemp = toLeft > 0; if (isOpenTemp != state && listener != null) { listener.setState(isOpenTemp); state = isOpenTemp; } } }
[4]给开关定义监听事件 具体什么时候出发回调事件:
public void setOnStateListener(OnStateListener listener) { this.listener = listener; } public interface OnStateListener { void setState(boolean isOpen); }
[5]处理滑动块滑动的逻辑 重写onTouchEvent方法 处理手指按下和移动的逻辑
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //按下的距离 downX = event.getX(); break; case MotionEvent.ACTION_MOVE: endX = event.getX(); moveX = endX - downX; toLeft = toLeft + moveX; if (toLeft <= 0) { toLeft = 0; } if (toLeft >= slideMax) { toLeft = slideMax; } downX = endX; break; case MotionEvent.ACTION_UP: isUp = true; float tHalf = tbg.getWidth() / 2; float sHalf = toLeft + sbg.getWidth() / 2; if (tHalf > sHalf) { toLeft = 0; } else { toLeft = slideMax; } break; } invalidate(); return true; }
[6]处理手指抬起的业务逻辑
case MotionEvent.ACTION_UP: isUp = true; float tHalf = tbg.getWidth() / 2; float sHalf = toLeft + sbg.getWidth() / 2; if (tHalf > sHalf) { toLeft = 0; } else { toLeft = slideMax; } break;
[7]实现开关的功能.
if (isUp) { isUp = false; boolean isOpenTemp = toLeft > 0; if (isOpenTemp != state && listener != null) { listener.setState(isOpenTemp); state = isOpenTemp; } }
[8]自定义开关的属性
8.1)在res下定义一个attrs文件
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ToggleView"> <attr name="state" format="boolean" /> </declare-styleable> </resources>
8.2)自己声明一个命名空间.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:toogle="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ngyb.choose.ToggleView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" toogle:state="true" /> </LinearLayout>
8.3)在构造方法里面获取我们声明的属性值
String namespace = "http://schemas.android.com/apk/res-auto"; boolean isOpen = attrs.getAttributeBooleanValue(namespace, "state", false);
8.4)更新开关的状态
public void setOpenState(boolean openState) { isUp = true; this.state = openState; }
https://github.com/nangongyibin7219/Android_OnOff
标签:state attr nullable prot Dimension content bre oid 移动
原文地址:https://www.cnblogs.com/nangongyibin/p/10322973.html