Android自定义控件实现滑动开关效果

Android自定义控件实现滑动开关效果,第1张

概述自定义开关控件 Android自定义控件一般有三种方式1、继承Android固有的控件,在Android原生控件的基础上,进行添加功能和逻辑。

自定义开关控件

 

@H_502_4@


AndroID自定义控件一般有三种方式
1、继承AndroID固有的控件,在AndroID原生控件的基础上,进行添加功能和逻辑。
2、继承VIEwGroup,这类自定义控件是可以往自己的布局里面添加其他的子控件的。
3、继承VIEw,这类自定义控件没有跟原生的控件有太多的相似的地方,也不需要在自己的肚子里添加其他的子控件。

ToggleVIEw自定义开关控件表征上没有跟AndroID原生的控件有什么相似的地方,而且在滑动的效果上也没有沿袭AndroID原生的地方,所以我们的自定义ToggleVIEw选择继承VIEw

 同样的自定义控件需要复写三个构造方法

//在布局中使用该控件的时候,而且有额外的style属性的时候调用该构造方法,public ToggleVIEw(Context context,AttributeSet attrs,int defStyle);//在布局中使用该控件的时候调用该构造方法public ToggleVIEw(Context context,AttributeSet attrs)//在Java代码中直接new该控件的时候,调用该构造方法public ToggleVIEw(Context context)

因为是自定义的控件,所以属性还是自己定义的比较好用一些。我们这里定义三个属性
1、背景图片
2、滑块的图片
3、布局中默认的开关的状态

所以就需要用到了自定义属性
在values目录下,新建xml文件,attrs.xml
在里面定义自己的属性

<?xml version="1.0" enCoding="utf-8"?><resources>  <declare-styleable name="toggle">   <attr name="switchBackground" format="reference" />   <attr name="slIDingBackground" format="reference" />   <attr name="toggleState" format="boolean" />  </declare-styleable></resources>

<declare-styleable name属性>是可以在R文件中找到该属性名称的

<attr>标签中,一个标签写一个属性 name属性表示属性名称,format表示属性类型

这里定义了三个属性名和属性类型。

属性和自定义控件的三个构造方法已经完成,就我们就可以在布局文件中添加自定义的控件了

<relativeLayout  xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:hss="http://schemas.androID.com/apk/res/com.hss.toggle" androID:layout_wIDth="match_parent" androID:layout_height="match_parent"  > <com.hss.toggle.ToggleVIEw  androID:ID="@+ID/toggleVIEw"  androID:layout_height="wrap_content"  androID:layout_wIDth="wrap_content"  androID:layout_centerInParent="true"  hss:switchBackground="@drawable/switch_background"  hss:slIDingBackground="@drawable/slIDe_button_background"  hss:toggleState="true"  >  </com.hss.toggle.ToggleVIEw></relativeLayout>

注意:在我自定义控件com.hss.toggle.ToggleVIEw中,部分属性是以androID开头的,部分属性是以hss(我自己定义的命名空间)开头的,这是为什么呢?

注意看本片代码第二行,

xmlns:hss="http://schemas.android.com/apk/res/com.hss.toggle"

我在这里写着样一行代码,就说明把values/attrs.xml中的每个条目都导入进来了,就可以直接使用我在attrs.xml里面的属性了

可以直接使用自定义的属性之后,问题应该聚焦到怎么在Java代码中获取到我自定义的属性的值呢?

根据命名空间和自定义属性的name值获取,看代码:

String namespace = "http://schemas.androID.com/apk/res/com.hss.toggle";  int toggle_switchbackground = attrs.getAttributeResourceValue(namespace,"switchBackground",-1);  int toggle_slIDingbackground = attrs.getAttributeResourceValue(namespace,"slIDingBackground",-1);  toggle_state = attrs.getAttributeBooleanValue(namespace,"toggleState",false);

看到没?该方法用到了attr参数,所以获取自定义属性值的 *** 作应该在两个参数的那里面执行。

整体的自定义控件的类见代码:

package com.hss.toggle;import androID.content.Context;import androID.graphics.Bitmap;import androID.graphics.BitmapFactory;import androID.graphics.Canvas;import androID.util.AttributeSet;import androID.util.Log;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;/** * 自定义开关控件 * @author hss */public class ToggleVIEw extends VIEw { private static final String TAG = "ToogleVIEw"; private Bitmap slIDing_background; private Bitmap switch_background; private boolean isSlIDing = false; private boolean toggle_state = false; private int downX; private mToggleStatechangelistener; // 构造方法,在xml文件布局的时候,指定了style的时候调用 public ToggleVIEw(Context context,int defStyle) {  super(context,attrs,defStyle); } // 构造方法,在xml文件中布局的时候,没有指定style的时候调用 public ToggleVIEw(Context context,AttributeSet attrs) {  this(context,0);  //在Java代码中 获取到xml中自定义属性对应的值  String namespace = "http://schemas.androID.com/apk/res/com.hss.toggle";  int toggle_switchbackground = attrs.getAttributeResourceValue(namespace,false);  Log.i(TAG,""+toggle_slIDingbackground+"  "+toggle_switchbackground);  // 设置自定义开关的图片  setToggleSwitchBackground(toggle_switchbackground);  setToggleSlIDingBackground(toggle_slIDingbackground);  setToggleState(toggle_state); } // 构造方法 在代码中new的时候调用 public ToggleVIEw(Context context) {  this(context,null); } /**  * 给滑动的控件设置背景图片  *   * @param toggle_slIDingbackground 图片ID  */ private voID setToggleSlIDingBackground(int toggle_slIDingbackground) {  slIDing_background = BitmapFactory.decodeResource(getResources(),toggle_slIDingbackground); } /**  * 给背景的控件,设置背景图片  *   * @param toggle_switchbackground 图片ID  */ private voID setToggleSwitchBackground(int toggle_switchbackground) {  switch_background = BitmapFactory.decodeResource(getResources(),toggle_switchbackground); } @OverrIDe protected voID onMeasure(int wIDthMeasureSpec,int heightmeasureSpec) {  //测量控件的大小,设置控件的大小为背景图片的大小  setMeasuredDimension(switch_background.getWIDth(),switch_background.getHeight()); } @OverrIDe protected voID onDraw(Canvas canvas) {  //开始画自定义控件,使用canvas对象先把背景图片画上来  canvas.drawBitmap(switch_background,null);  if (isSlIDing) {  //如果是滑动状态   //控件距离左边的相对距离为:(控件每时每刻的距离自己左上方的焦点的x轴距离)-(控件本身一半的x轴宽度)   int left = downX - slIDing_background.getWIDth() / 2;   //控件最大的滑动距离(距离左边最大的距离)就是:(背景图片的宽度)-(滑块图片的宽度)   int rightAlign = switch_background.getWIDth()- slIDing_background.getWIDth();   //如果距离左边的距离小于0,,就不让他继续往左边动了   if (left < 0) {    left = 0;   } else if (left > rightAlign) {    //如果距离左边的距离》应该距离左边的最大距离,也不让他往右边移动了    left = rightAlign;   }   //控制好属性之后就可以时时刻刻的跟着画了   canvas.drawBitmap(slIDing_background,left,null);  } else {   //如果不滑动,则根据控件的属性中开关的状态,来画滑块的位置   if (toggle_state) {    //如果开关状态为真,滑块移动到最右边    int left = switch_background.getWIDth() - slIDing_background.getWIDth();    canvas.drawBitmap(slIDing_background,null);   } else {    //如果开关状态为假,滑块移动到最左边    canvas.drawBitmap(slIDing_background,null);   }  }  super.onDraw(canvas); } @OverrIDe public boolean ontouchEvent(MotionEvent event) {  //重写触摸事件  int action = event.getAction();  switch (action) {  case MotionEvent.ACTION_DOWN:   //开始点击的时候,是否滑动置为真,获取到当前手指的距离   isSlIDing = true;   downX = (int) event.getX();   break;  case MotionEvent.ACTION_MOVE:   downX = (int) event.getX();   break;  case MotionEvent.ACTION_UP:   //当点击结束的时候将是否滑动记为假,获取到移动的x轴的坐标   downX = (int) event.getX();   isSlIDing = false;   //获取到背景图片中间的那个值   int center = switch_background.getWIDth() / 2;   boolean state = downX > center;   //如果先后的状态不相同,则将新的状态赋给成员变量,然后调用监听的方法   if (toggle_state != state) {    toggle_state = state;    if (null != mToggleStatechangelistener) {     mToggleStatechangelistener       .onToggleState(toggle_state);    }   }   break;  }  //调用一次onDraw()方法  invalIDate();  return true; } //给自定义开关控件设置监听的方法 public voID setonToggleStatelinstener(OnToggleStatechangelistener Listen){  mToggleStatechangelistener = Listen; } public voID setToggleState(boolean b) {  toggle_state = b; } //监听回调接口,方法由实现接口的类实现 public interface OnToggleStatechangelistener {  public voID onToggleState(boolean state); }}

到此,我们的自定义控件部分的逻辑就写完了,,借下来再MainActivity中调用一下

package com.hss.toggle;import androID.app.Activity;import androID.os.Bundle;import com.hss.toggle.ToggleVIEw.OnToggleStatechangelistener;import com.hss.toggle.utils.ToastUtil;public class MainActivity extends Activity{ private ToggleVIEw toggleVIEw; @OverrIDe protected voID onCreate(Bundle savedInstanceState) {  // Todo auto-generated method stub  super.onCreate(savedInstanceState);  setContentVIEw(R.layout.activity_main);  toggleVIEw = (ToggleVIEw) findVIEwByID(R.ID.toggleVIEw);  toggleVIEw.setonToggleStatelinstener(new OnToggleStatechangelistener() {   @OverrIDe   public voID onToggleState(boolean state) {    showToast(state);   }  }); } //这里调用到的自己封装的一个快速dToast的工具类 private voID showToast(boolean state) {  ToastUtil.makeSuddenlyToast(getApplicationContext(),state?"开":"关"); }}

ToastUtil类如下:

package com.hss.toggle.utils;import androID.content.Context;import androID.Widget.Toast;/** * @Title Toast工具类 * @author hss */public class ToastUtil { private static Toast toast; /**  * d出短时间Toast  * @param context 上下文对象  * @param text 要d出的文字  */ public static voID makeShortToast(Context context,String text){  toast = Toast.makeText(context,text,Toast.LENGTH_SHORT);  toast.show(); } /**  * d出长时间的Toast  * @param context 上下文对象  * @param text 要d出的文字  */ public static voID makeLongToast(Context context,Toast.LENGTH_LONG);  toast.show(); } /**  * 单例Toast  * @param context 上下文对象  * @param text 要d出的文字  */ public static voID makeSuddenlyToast(Context context,String text){  if(toast==null){   toast = Toast.makeText(context,Toast.LENGTH_SHORT);  }  toast.setText(text);  toast.show(); }}

总结一下,其实本次自定义控件的步骤如下:
1、在values/attrs.xml自定义属性和属性值的数据类型
2、在Java代码中定义自定义控件类,继承VIEw或者VIEwGroup或者AndroID原生的控件,实现构造方法,获取到自定义属性的值,并且编写对应的逻辑和点击事件。
3、在布局文件中使用自定义控件和自定义属性(注意命名空间)。
4、在MainActivity中调用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android自定义控件实现滑动开关效果全部内容,希望文章能够帮你解决Android自定义控件实现滑动开关效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1148819.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存