自定义控件1

mac2022-06-30  112

1.自定义属性values/attrs.xml

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="ToggleView"> <attr name="switch_background" format="reference" /> <attr name="slide_button" format="reference" /> <attr name="switch_state" format="boolean" /> </declare-styleable> </resources> 2.view的java文件:

package zdl.switchbutton.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * 自定义开关 * */ public class ToggleView extends View { private Bitmap switchBackgroupBitmap; // 背景图片 private Bitmap slideButtonBitmap; // 滑块图片 private Paint paint; // 画笔 private boolean mSwitchState = false; // 开关状态, 默认false private float currentX; /** * 用于代码创建控件 * * @param context */ public ToggleView(Context context) { super(context); init(); } /** * 用于在xml里使用, 可指定自定义属性 * * @param context * @param attrs */ public ToggleView(Context context, AttributeSet attrs) { super(context, attrs); init(); // 获取配置的自定义属性 String namespace = "http://toly.android.com/apk/res/zdl.switchbutton.view.ToggleView"; int switchBackgroundResource = attrs.getAttributeResourceValue(namespace, "switch_background", -1); int slideButtonResource = attrs.getAttributeResourceValue(namespace, "slide_button", -1); mSwitchState = attrs.getAttributeBooleanValue(namespace, "switch_state", false); setSwitchBackgroundResource(switchBackgroundResource); setSlideButtonResource(slideButtonResource); } /** * 用于在xml里使用, 可指定自定义属性, 如果指定了样式, 则走此构造函数 *F:\Android\SwitchButton\app\src\main\java\zdl\switchbutton\view\ToggleView.java * zdl.switchbutton.view.ToggleView * @param context * @param attrs * @param defStyle */ public ToggleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { paint = new Paint(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(switchBackgroupBitmap.getWidth(), switchBackgroupBitmap.getHeight()); } // Canvas 画布, 画板. 在上边绘制的内容都会显示到界面上. @Override protected void onDraw(Canvas canvas) { // 1. 绘制背景 canvas.drawBitmap(switchBackgroupBitmap, 0, 0, paint); // 2. 绘制滑块 if (isTouchMode) { // 根据当前用户触摸到的位置画滑块 // 让滑块向左移动自身一半大小的位置 float newLeft = currentX - slideButtonBitmap.getWidth() / 2.0f; int maxLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth(); // 限定滑块范围 if (newLeft < 0) { newLeft = 0; // 左边范围 } else if (newLeft > maxLeft) { newLeft = maxLeft; // 右边范围 } canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint); } else { // 根据开关状态boolean, 直接设置图片位置 if (mSwitchState) {// 开 int newLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth(); canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint); } else {// 关 canvas.drawBitmap(slideButtonBitmap, 0, 0, paint); } } } boolean isTouchMode = false; private OnSwitchListener onSwitchListener; // 重写触摸事件, 响应用户的触摸. @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isTouchMode = true; System.out.println("event: ACTION_DOWN: " + event.getX()); currentX = event.getX(); break; case MotionEvent.ACTION_MOVE: System.out.println("event: ACTION_MOVE: " + event.getX()); currentX = event.getX(); break; case MotionEvent.ACTION_UP: isTouchMode = false; System.out.println("event: ACTION_UP: " + event.getX()); currentX = event.getX(); float center = switchBackgroupBitmap.getWidth() / 2.0f; // 根据当前按下的位置, 和控件中心的位置进行比较. boolean state = currentX > center; // 如果开关状态变化了, 通知界面. 里边开关状态更新了. if (state != mSwitchState && onSwitchListener != null) { // 把最新的boolean, 状态传出去了 onSwitchListener.onStateUpdate(state); } mSwitchState = state; break; default: break; } // 重绘界面 invalidate(); // 会引发onDraw()被调用, 里边的变量会重新生效.界面会更新 return true; // 消费了用户的触摸事件, 才可以收到其他的事件. } /** * 设置背景图 * * @param switchBackground */ public void setSwitchBackgroundResource(int switchBackground) { switchBackgroupBitmap = BitmapFactory.decodeResource(getResources(), switchBackground); } /** * 设置滑块图片资源 * * @param slideButton */ public void setSlideButtonResource(int slideButton) { slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideButton); } /** * 设置开关状态 */ public void setSwitchState(boolean mSwitchState) { this.mSwitchState = mSwitchState; } public interface OnSwitchListener { // 状态回调, 把当前状态传出去 void onStateUpdate(boolean state); } public void setOnSwitchListener(OnSwitchListener onSwitchListener) { this.onSwitchListener = onSwitchListener; } }

3.layout中使用

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:toly="http://toly.android.com/apk/res/zdl.switchbutton.view.ToggleView" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <zdl.switchbutton.view.ToggleView android:id="@+id/toggleView" toly:switch_background="@drawable/switch_background" toly:slide_button="@drawable/slide_button" toly:switch_state="false" android:layout_width="20dp" android:layout_height="wrap_content"/> </LinearLayout> 4.MainActivity.java中:

package zdl.switchbutton; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import zdl.switchbutton.view.ToggleView; public class MainActivity extends AppCompatActivity { private Toolbar mTb; private ToggleView toggleView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toggleView = (ToggleView) findViewById(R.id.toggleView); // 设置开关更新监听 toggleView.setOnSwitchListener(new ToggleView.OnSwitchListener(){ @Override public void onStateUpdate(boolean state) { Toast.makeText(getApplicationContext(), "state: " + state, 0).show(); } }); }

转载于:https://www.cnblogs.com/toly-top/p/9782039.html

最新回复(0)