android自定义开关控件-SlideSwitch的实例

android自定义开关控件-SlideSwitch的实例,第1张

概述iphone上有开关控件,很漂亮,其实android4.0以后也有switch控件,但是只能用在4.0以后的系统中,这就失去了其使用价值,而且我觉得它的界面也不是很好看。最近看到了百度魔拍上面的一个控件,觉得很漂亮啊,然后反编

iphone上有开关控件,很漂亮,其实androID4.0以后也有switch控件,但是只能用在4.0以后的系统中,这就失去了其使用价值,而且我觉得它的界面也不是很好看。最近看到了百度魔拍上面的一个控件,觉得很漂亮啊,然后反编译了下,尽管没有混淆过,但是还是不好读,然后就按照自己的想法写了个,功能和百度魔拍类似。

下面是百度魔拍的效果和SlIDeSwitch的效果

一、原理

继承自vIEw类,overrIDe其onDraw函数,把两个背景图(一个灰的一个红的)和一个开关图(圆开关)通过canvas画出来;同时overrIDe其ontouchEvent函数,实现滑动效果;最后开启一个线程做动画,实现缓慢滑动的效果。

二、代码

SlIDeSwitch.java

package com.example.hellojni;  import androID.content.Context; import androID.content.res.Resources; import androID.graphics.Bitmap; import androID.graphics.BitmapFactory; import androID.graphics.Canvas; import androID.graphics.color; import androID.graphics.Paint; import androID.graphics.Rect; import androID.graphics.Typeface; import androID.util.AttributeSet; import androID.util.Log; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.vIEw.VIEwGroup.LayoutParams;  /**  * SlIDeSwitch 仿iphone滑动开关组件,仿百度魔图滑动开关组件  * 组件分为三种状态:打开、关闭、正在滑动<br/>  * 使用方法:      * <pre>SlIDeSwitch slIDeSwitch = new SlIDeSwitch(this);  *slIDeSwitch.setonSwitchChangedListener(onSwitchChangedListener);  *linearLayout.addVIEw(slIDeSwitch); </pre> 注:也可以加载在xml里面使用  * @author scott  *  */ public class SlIDeSwitch extends VIEw {   public static final String TAG = "SlIDeSwitch";   public static final int SWITCH_OFF = 0;//关闭状态   public static final int SWITCH_ON = 1;//打开状态   public static final int SWITCH_SCROliNG = 2;//滚动状态      //用于显示的文本   private String mOnText = "打开";   private String mOffText = "关闭";    private int mSwitchStatus = SWITCH_OFF;    private boolean mHasScrolled = false;//表示是否发生过滚动    private int mSrcX = 0,mdstX = 0;      private int mBmpWIDth = 0;   private int mBmpHeight = 0;   private int mThumbWIDth = 0;    private   Paint mPaint = new Paint(Paint.ANTI_AliAS_FLAG);      private OnSwitchChangedListener mOnSwitchChangedListener = null;    //开关状态图   Bitmap mSwitch_off,mSwitch_on,mSwitch_thumb;    public SlIDeSwitch(Context context)    {     this(context,null);   }    public SlIDeSwitch(Context context,AttributeSet attrs)    {     super(context,attrs);     init();   }    public SlIDeSwitch(Context context,AttributeSet attrs,int defStyle)   {     super(context,attrs,defStyle);     init();   }    //初始化三幅图片   private voID init()   {     Resources res = getResources();     mSwitch_off = BitmapFactory.decodeResource(res,R.drawable.bg_switch_off);     mSwitch_on = BitmapFactory.decodeResource(res,R.drawable.bg_switch_on);     mSwitch_thumb = BitmapFactory.decodeResource(res,R.drawable.switch_thumb);     mBmpWIDth = mSwitch_on.getWIDth();     mBmpHeight = mSwitch_on.getHeight();     mThumbWIDth = mSwitch_thumb.getWIDth();   }    @OverrIDe   public voID setLayoutParams(LayoutParams params)    {     params.wIDth = mBmpWIDth;     params.height = mBmpHeight;     super.setLayoutParams(params);   }      /**    * 为开关控件设置状态改变监听函数    * @param onSwitchChangedListener 参见 {@link OnSwitchChangedListener}    */   public voID setonSwitchChangedListener(OnSwitchChangedListener onSwitchChangedListener)   {     mOnSwitchChangedListener = onSwitchChangedListener;   }      /**    * 设置开关上面的文本    * @param onText 控件打开时要显示的文本    * @param offText 控件关闭时要显示的文本    */   public voID setText(final String onText,final String offText)   {     mOnText = onText;     mOffText =offText;     invalIDate();   }      /**    * 设置开关的状态    * @param on 是否打开开关 打开为true 关闭为false    */   public voID setStatus(boolean on)   {     mSwitchStatus = ( on ? SWITCH_ON : SWITCH_OFF);   }      @OverrIDe   public boolean ontouchEvent(MotionEvent event)   {     int action = event.getAction();     Log.d(TAG,"ontouchEvent x=" + event.getX());     switch (action) {     case MotionEvent.ACTION_DOWN:       mSrcX = (int) event.getX();       break;     case MotionEvent.ACTION_MOVE:       mdstX = Math.max( (int) event.getX(),10);       mdstX = Math.min( mdstX,62);       if(mSrcX == mdstX)         return true;       mHasScrolled = true;       AnimationTransRunnable aTransRunnable = new AnimationTransRunnable(mSrcX,mdstX,0);       new Thread(aTransRunnable).start();       mSrcX = mdstX;       break;     case MotionEvent.ACTION_UP:       if(mHasScrolled == false)//如果没有发生过滑动,就意味着这是一次单击过程       {         mSwitchStatus = Math.abs(mSwitchStatus-1);         int xFrom = 10,xTo = 62;         if(mSwitchStatus == SWITCH_OFF)         {           xFrom = 62;           xTo = 10;         }         AnimationTransRunnable runnable = new AnimationTransRunnable(xFrom,xTo,1);         new Thread(runnable).start();       }       else       {         invalIDate();         mHasScrolled = false;       }       //状态改变的时候 回调事件函数       if(mOnSwitchChangedListener != null)       {         mOnSwitchChangedListener.onSwitchChanged(this,mSwitchStatus);       }       break;      default:       break;     }     return true;   }    @OverrIDe   protected voID onSizeChanged(int w,int h,int olDW,int oldh)   {     super.onSizeChanged(w,h,olDW,oldh);   }    @OverrIDe   protected voID onDraw(Canvas canvas)   {     super.onDraw(canvas);     //绘图的时候 内部用到了一些数值的硬编码,其实不太好,     //主要是考虑到图片的原因,图片周围有透明边界,所以要有一定的偏移     //硬编码的数值只要看懂了代码,其实可以理解其含义,可以做相应改进。     mPaint.setTextSize(14);     mPaint.setTypeface(Typeface.DEFAulT_BolD);          if(mSwitchStatus == SWITCH_OFF)     {       drawBitmap(canvas,null,mSwitch_off);       drawBitmap(canvas,mSwitch_thumb);       mPaint.setcolor(color.rgb(105,105,105));       canvas.translate(mSwitch_thumb.getWIDth(),0);       canvas.drawText(mOffText,20,mPaint);     }     else if(mSwitchStatus == SWITCH_ON)     {       drawBitmap(canvas,mSwitch_on);       int count = canvas.save();       canvas.translate(mSwitch_on.getWIDth() - mSwitch_thumb.getWIDth(),0);       drawBitmap(canvas,mSwitch_thumb);       mPaint.setcolor(color.WHITE);       canvas.restoretoCount(count);       canvas.drawText(mOnText,17,mPaint);     }     else //SWITCH_SCROliNG     {       mSwitchStatus = mdstX > 35 ? SWITCH_ON : SWITCH_OFF;       drawBitmap(canvas,new Rect(0,mBmpHeight),(int)mdstX,mSwitch_on);       mPaint.setcolor(color.WHITE);       canvas.drawText(mOnText,mPaint);        int count = canvas.save();       canvas.translate(mdstX,new Rect(mdstX,mBmpWIDth,mBmpWIDth - mdstX,mSwitch_off);       canvas.restoretoCount(count);        count = canvas.save();       canvas.clipRect(mdstX,mBmpHeight);       canvas.translate(mThumbWIDth,0);       mPaint.setcolor(color.rgb(105,105));       canvas.drawText(mOffText,mPaint);       canvas.restoretoCount(count);        count = canvas.save();       canvas.translate(mdstX - mThumbWIDth / 2,mSwitch_thumb);       canvas.restoretoCount(count);     }    }    public voID drawBitmap(Canvas canvas,Rect src,Rect dst,Bitmap bitmap)   {     dst = (dst == null ? new Rect(0,bitmap.getWIDth(),bitmap.getHeight()) : dst);     Paint paint = new Paint();     canvas.drawBitmap(bitmap,src,dst,paint);   }    /**    * AnimationTransRunnable 做滑动动画所使用的线程    */   private class AnimationTransRunnable implements Runnable   {     private int srcX,dstX;     private int duration;      /**      * 滑动动画      * @param srcX 滑动起始点      * @param dstX 滑动终止点      * @param duration 是否采用动画,1采用,0不采用      */     public AnimationTransRunnable(float srcX,float dstX,final int duration)     {       this.srcX = (int)srcX;       this.dstX = (int)dstX;       this.duration = duration;     }      @OverrIDe     public voID run()      {       final int patch = (dstX > srcX ? 5 : -5);       if(duration == 0)       {         SlIDeSwitch.this.mSwitchStatus = SWITCH_SCROliNG;         SlIDeSwitch.this.postInvalIDate();       }       else       {         Log.d(TAG,"start Animation: [ " + srcX + "," + dstX + " ]");         int x = srcX + patch;         while (Math.abs(x-dstX) > 5)          {           mdstX = x;           SlIDeSwitch.this.mSwitchStatus = SWITCH_SCROliNG;           SlIDeSwitch.this.postInvalIDate();           x += patch;           try            {             Thread.sleep(10);           }            catch (InterruptedException e)           {             e.printstacktrace();           }         }         mdstX = dstX;         SlIDeSwitch.this.mSwitchStatus = mdstX > 35 ? SWITCH_ON : SWITCH_OFF;         SlIDeSwitch.this.postInvalIDate();       }     }    }    public static interface OnSwitchChangedListener   {     /**      * 状态改变 回调函数      * @param status SWITCH_ON表示打开 SWITCH_OFF表示关闭      */     public abstract voID onSwitchChanged(SlIDeSwitch obj,int status);   }  } 

layout xml

<?xml version="1.0" enCoding="utf-8"?> <linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"   androID:layout_wIDth="fill_parent"   androID:layout_height="fill_parent"   androID:background="#fdfdfd"   androID:orIEntation="vertical"   androID:paddingleft="10dip"   androID:paddingRight="10dip" >    <ImageVIEw     androID:ID="@+ID/imageVIEw1"     androID:layout_wIDth="fill_parent"     androID:layout_height="wrap_content"     androID:src="@drawable/top" />    <relativeLayout     androID:layout_wIDth="fill_parent"     androID:layout_height="wrap_content" >      <TextVIEw       androID:ID="@+ID/textVIEw1"       androID:layout_wIDth="wrap_content"       androID:layout_height="wrap_content"       androID:layout_alignParentleft="true"       androID:layout_centerVertical="true"       androID:text="网络构图"       androID:textSize="15sp" />      <com.example.hellojni.SlIDeSwitch       androID:ID="@+ID/slIDeSwitch1"       androID:layout_wIDth="116dip"       androID:layout_height="46dip"       androID:layout_alignParentRight="true"       androID:layout_centerVertical="true" />   </relativeLayout>    <relativeLayout     androID:layout_wIDth="fill_parent"     androID:layout_height="wrap_content" >      <TextVIEw       androID:ID="@+ID/textVIEw2"       androID:layout_wIDth="wrap_content"       androID:layout_height="wrap_content"       androID:layout_alignParentleft="true"       androID:layout_centerVertical="true"       androID:text="保留原图"       androID:textSize="15sp" />      <com.example.hellojni.SlIDeSwitch       androID:ID="@+ID/slIDeSwitch2"       androID:layout_wIDth="116dip"       androID:layout_height="46dip"       androID:layout_alignParentRight="true"       androID:layout_centerVertical="true" />   </relativeLayout>    <relativeLayout     androID:layout_wIDth="fill_parent"     androID:layout_height="wrap_content" >      <TextVIEw       androID:ID="@+ID/textVIEw3"       androID:layout_wIDth="wrap_content"       androID:layout_height="wrap_content"       androID:layout_alignParentleft="true"       androID:layout_centerVertical="true"       androID:text="拍照声音"       androID:textSize="15sp" />      <com.example.hellojni.SlIDeSwitch       androID:ID="@+ID/slIDeSwitch3"       androID:layout_wIDth="116px"       androID:layout_height="46px"       androID:layout_alignParentRight="true"       androID:layout_centerVertical="true" />   </relativeLayout>    <TextVIEw     androID:ID="@+ID/textVIEwTip"     androID:layout_wIDth="fill_parent"     androID:layout_height="wrap_content"     androID:gravity="center"     androID:text="TextVIEw" />  </linearLayout> 

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

总结

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

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

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存