自定义开关控件(ToggleView)继承View实现
2016-11-27 12:36
375 查看
package yuan.jxau.cn.toggleview.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; import yuan.jxau.cn.toggleview.R; /** * Created by 编程只服JAVA on 2016.11.26. */ /** * 自定义开关 * * Android界面绘制流程 * 测量 摆放 绘制 * measure->layout->draw * | | | * onMeasure->onLayout->onDraw 重写这些方法,实现自定义控件 * * onResume()方法之后执行 * * View * onMeasure()(在这个方法里面指定自己的宽高)->onDraw()(绘制自己的内容) * * ViewGroup * onMeasure(指定自己的宽高,所有子view的宽高)()->onLayout()(摆放所有子view)->onDraw()(绘制内容) */ public class ToggleView extends View { private Bitmap switchBackgroud; private Bitmap slideBackground; private Boolean switchState; private Paint paint; private float currentX; private Boolean isTouchMode = false; private OnSwitchStateUpdateListener onSwitchStateUpdateListener; /** * 用于代码创建控件 * @param context */ public ToggleView(Context context) { super(context); init(); } private void init() { paint = new Paint(); } /** * 用于在xml里使用,可指定自定义属性 * @param context * @param attrs */ public ToggleView(Context context, AttributeSet attrs) { super(context, attrs); init(); String namespace = "http://schemas.android.com/apk/res-auto"; int switchResouceBackground = attrs.getAttributeResourceValue(namespace ,"switch_background", R.drawable.switch_background); int slideResouceBackGround = attrs.getAttributeResourceValue(namespace , "slide_button" , R.drawable.slide_button); Boolean isOpen = attrs.getAttributeBooleanValue(namespace,"switch_state",false); setSlideBackgroundResource(slideResouceBackGround); setSwitchBackgroundResource(switchResouceBackground); setState(isOpen); } /** * 用于在xml里使用,可指定自定义属性,如果指定了样式,则走此构造函数 * @param context * @param attrs * @param defStyleAttr */ public ToggleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //重写测量方法 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(switchBackgroud.getWidth(),switchBackgroud.getHeight()); } //重写绘制方法 @Override protected void onDraw(Canvas canvas) { //1.绘制背景 canvas.drawBitmap(switchBackgroud,0,0,paint); //2.绘制滑块 if (isTouchMode){ //用户触摸状态 float newLeft = currentX - slideBackground.getWidth()/2.0f; /** * 限定滑块滑动范围 */ int maxLeft = switchBackgroud.getWidth() - slideBackground.getWidth(); if(newLeft < 0){ newLeft = 0; }else if (newLeft > maxLeft){ newLeft = maxLeft; } //根据当前用户触摸到的位置绘制滑块 canvas.drawBitmap(slideBackground, newLeft , 0,paint); }else{ if (switchState){ //打开状态 int newLeft = switchBackgroud.getWidth() - slideBackground.getWidth(); canvas.drawBitmap(slideBackground,newLeft,0,paint); }else { //关闭状态 canvas.drawBitmap(slideBackground,0,0,paint); } } } //重写触摸事件,响应用户的触摸 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN : currentX = event.getX(); isTouchMode = true; break; case MotionEvent.ACTION_MOVE : currentX = event.getX(); break; case MotionEvent.ACTION_UP: isTouchMode = false; currentX = event.getX(); float center = switchBackgroud.getWidth()/2.0f; Boolean state = currentX >center; /** * 如果ToggleView的状态发生改变,通知外面ToggleView的状态已经发生了变化 */ if (state != switchState && onSwitchStateUpdateListener != null){ onSwitchStateUpdateListener.onStateUpdate(state); } switchState = state; break; } //#######重绘界面,onDraw()被调用,里面的变量会重新生效,界面会更新######## invalidate(); return true;//返回true:消费了用户的触摸事件 } /** * 设置背景图片 * @param switch_background */ public void setSwitchBackgroundResource(int switch_background) { switchBackgroud = BitmapFactory.decodeResource(getResources(), switch_background); } /** * 设置滑块的背景图片 * @param slide_button */ public void setSlideBackgroundResource(int slide_button) { slideBackground = BitmapFactory.decodeResource(getResources(), slide_button); } public void setState(boolean switchState) { //状态回调,将当前状态传出去 this.switchState = switchState; } //状态变化的监听方法,当ToggleView的状态发生改变的时候,会通知外面。 public void setOnSwitchStateUpdateListener(OnSwitchStateUpdateListener onSwitchStateUpdateListener) { this.onSwitchStateUpdateListener = onSwitchStateUpdateListener; } public interface OnSwitchStateUpdateListener{ void onStateUpdate(Boolean state); } }
自定义属性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>布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="yuan.jxau.cn.toggleview.MainActivity">
<yuan.jxau.cn.toggleview.view.ToggleView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/taggleview"
android:background="@android:color/transparent"/>
</RelativeLayout>
相关文章推荐
- 继承View自定义开关控件
- Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- 基于ViewFlipper实现的自定义新手指引控件.
- 【Android界面实现】自定义滑动开关控件的实现与使用
- 【自定义视图控件】入门篇----继承View以及主要的函数
- qt利用委托:QStyledItemDelegate,实现tableview 的表格项的自定义显示,如插入图片,绘制控件
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)
- android自定义Tabs控件,基于ScrollView+ViewPager实现。
- IOS自定义View实现相应的控件点击方法以及代理的总结(附代码)
- 安卓开发笔记——自定义HorizontalScrollView控件(实现QQ5.0侧滑效果)
- 基于ViewFlipper实现的自定义新手指引控件
- 小米3系统计算器自定义开关控件-MySwitchView
- Android高手进阶教程(二十七)之---基于ViewFlipper实现的自定义新手指引控件.
- 自定义UIScrollView 滚动条(适合大部分继承自UIScrollView的控件,如UITextView,UITableView等)
- 自定义实现MPVolumeView音量控件
- 自定义ImageView控件,实现点击高亮图标
- UISplitViewController-分割控件自定义分割宽度是无法实现的
- 基于ViewFlipper实现的自定义新手指引控件.