首页 > 学院 > 开发设计 > 正文

自定义View--SwichButton

2019-11-09 18:03:32
字体:
来源:转载
供稿:网友

SwichButton是一个继承自View自定义开关,刚好也通过这个自定义View来总结回顾下

通过java代码来设置属性

** 第一步: 新建一个命名为SwichButton的类,继承自View,重写三个构造方法

//在代码中设置属性使用的构造方法 public SwichButton(Context context) { super(context); } //在xml中定义属性使用的的构造方法 public SwichButton(Context context, AttributeSet attrs) { super(context, attrs); }//在xml中定义属性,并且带有样式的构造方法 public SwichButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }

第二步:在布局文件中使用

<com.cd.swichdemo.SwichButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/swichbutton"/>

注意:自定义View要使用完整路径名称,系统控件则不需要

第三步:在Activity中找到这个控件的id

第四步:分析自定义的控件的需求,包括要设置什么属性,有几种状态,等等

比如,分析这个自定义开关需要设置开关背景,需要设置滑块背景,以及开和关两种状态,那么就需要分别定义设置开关背景的方法,设计滑块背景的方法和设置状态的方法

mSwichButton.setSwichBackgroundResouce(R.drawable.switch_background); mSwichButton.setSwichButtonResource(R.drawable.slide_button); mSwichButton.setSwichState(false);

所以要在自定义的SwichButton中创建这三个方法

public void setSwichState(boolean swichState) { mSwichState = swichState; }

public void setSwichBackgroundResouce(int swichBackgroundResouce) { mBackgroundResouce = BitmapFactory.decodeResource(getResources(), swichBackgroundResouce);}public void setSwichButtonResource(int slide_button) { mSlidbutton = BitmapFactory.decodeResource(getResources(), slide_button);}

可以手动创建也可以使用快捷键,setSwichState方法中mSwichState默认为false,setSwichBackgroundResouce(int swichBackgroundResouce)setSwichButtonResource(int slide_button)方法中拿到设置的图片资源,转换成bitmap对象

补充:

Android View绘制流程

测量 摆放 大小

View :onMeasure(测量自己的宽高) –》onDraw(绘制自己的内容)

viewGrounp: onMeasure(测量自己的宽高,所有子View的宽高) –》onLayout(摆放内部控件,只有容器才要重写这个方法) –》onDraw(绘制自己的内容) */

第五步:测量控件的宽高:该控件的宽高就是图片的宽高,也可以写死或者使用dimens

@Override PRotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(mBackgroundResouce.getWidth(), mBackgroundResouce.getHeight()); }

重写onMeasure方法,调用setMeasuredDimension传入宽高,这样这个控件的宽高就确定了

第六步:绘制视图,重写onDraw方法

@Override protected void onDraw(Canvas canvas) { //绘制背景 canvas.drawBitmap(mBackgroundResouce, 0, 0, mPaint); if (isTouchMode) {//如果是触摸模式,则执行if //这些要画图理解,位置都是从控件的左上角开始计算的,移动即计算位移距离 float newLeft = mCurrentX - mSlidbutton.getWidth() / 2.0f; int maxLeft = mBackgroundResouce.getWidth() - mSlidbutton.getWidth(); //控制滑块按钮超过背景区域 if (newLeft < 0) { newLeft = 0; } else if (newLeft > maxLeft) { newLeft = maxLeft; } //绘制滑块 canvas.drawBitmap(mSlidbutton, newLeft, 0, mPaint); } else {//非触摸模式则通过设置的状态来判断开关 if (mSwichState) {//开 int newLeft = mBackgroundResouce.getWidth() - mSlidbutton.getWidth(); canvas.drawBitmap(mSlidbutton, newLeft, 0, mPaint); } else {//关 canvas.drawBitmap(mSlidbutton, 0, 0, mPaint); } } }

绘制视图必须有一支笔,创建一个init()方法,在里面创建一个paint,然后在每个构造方法中调用init()

private void init() { mPaint = new Paint(); }

笔创建好了,才能在onDraw中使用,这里的paint,不建议直接在onDraw中创建

第七步:重写触摸事件

@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: isTouchMode = false; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); //控件中间的位置, float center = mBackgroundResouce.getWidth() / 2.0f; //根据当前按下的位置和控件中心的位置进行比较 boolean state = mCurrentX > center; //如果当前状态变化了,通知开关切换状态 if (state != mSwichState && mSwichStateChangeListen != null) { mSwichStateChangeListen.stateChange(state); } //更新mSwichState 状态 mSwichState = state; break; case MotionEvent.ACTION_MOVE: isTouchMode = true; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); break; case MotionEvent.ACTION_DOWN: isTouchMode = true; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); break; } invalidate();//一定要调用这个方法哦,不然不会重新绘制,导致滑动没效果 return true;//返回true表示消费该事件 }

第八步:定义接口设置状态监听回调

swichStateChangeListen mSwichStateChangeListen; public interface swichStateChangeListen { void stateChange(boolean state); } public void setSwichStateChangeListen(swichStateChangeListen swichStateChangeListen) { mSwichStateChangeListen = swichStateChangeListen; }

在ACTION_UP的时候调用

case MotionEvent.ACTION_UP: isTouchMode = false; mCurrentX = event.getX(); System.out.println("==:" + mCurrentX); //控件中间的位置, float center = mBackgroundResouce.getWidth() / 2.0f; //根据当前按下的位置和控件中心的位置进行比较 boolean state = mCurrentX > center; //如果当前状态变化了,通知开关切换状态 if (state != mSwichState && mSwichStateChangeListen != null) { mSwichStateChangeListen.stateChange(state); } mSwichState = state; break;

在Activity中设置监听

mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } });

使用如下

public class MainActivity extends AppCompatActivity { SwichButton mSwichButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSwichButton= (SwichButton) findViewById(R.id.swichbutton); mSwichButton.setSwichBackgroundResouce(R.drawable.switch_background); mSwichButton.setSwichButtonResource(R.drawable.slide_button); mSwichButton.setSwichState(false); mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } }); }}

通过xml来控制属性

第一步:在values下新建attrs.xml,如果已经有了就直接添加属性

<resources> <declare-styleable name="SwichButton"> <attr name="SwichBackground" format="reference"/> <attr name="swichButtonRes" format="reference"/> <attr name="swich_state" format="boolean"/> </declare-styleable></resources>

第二步:

在自定义视图中获取到属性,进行处理

//在xml中定义属性使用的的构造方法 public SwichButton(Context context, AttributeSet attrs) { super(context, attrs); init(); String nameSpace="http://schemas.android.com/apk/res-auto"; int swichBackground = attrs.getAttributeResourceValue(nameSpace, "SwichBackground", -1); int swichButtonRes = attrs.getAttributeResourceValue(nameSpace, "swichButtonRes", -1); boolean swich_state = attrs.getAttributeBooleanValue(nameSpace, "swich_state", false); setSwichBackgroundResouce(swichBackground); setSwichButtonResource(swichButtonRes); setSwichState(swich_state); }

第三步:在布局文件中设置

<com.cd.swichdemo.SwichButton android:layout_width="wrap_content" cd:SwichBackground="@drawable/switch_background" cd:swichButtonRes="@drawable/slide_button" cd:swich_state="false" android:layout_height="wrap_content" android:id="@+id/swichbutton"/>

记得在跟布局上添加命名空间:http://schemas.android.com/apk/res-auto 这样就完成了,activity中不需要在去另外设置,如下

public class MainActivity extends AppCompatActivity { SwichButton mSwichButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSwichButton= (SwichButton) findViewById(R.id.swichbutton); mSwichButton.setSwichStateChangeListen(new SwichButton.swichStateChangeListen() { @Override public void stateChange(boolean state) { Toast.makeText(MainActivity.this, "state:" + state, Toast.LENGTH_SHORT).show(); } }); }}

demo下载:http://download.csdn.net/detail/cdhahaha/9748837


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表