1. 程式人生 > >android自定義開關控制元件-SlideSwitch

android自定義開關控制元件-SlideSwitch

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

1.效果

iphone上有開關控制元件,很漂亮,其實android4.0以後也有switch控制元件,但是隻能用在4.0以後的系統中,這就失去了其使用價值,而且我覺得它的介面也不是很好看。最近看到了百度魔拍上面的一個控制元件,覺得很漂亮啊,然後反編譯了下,儘管沒有混淆過,但是還是不好讀,然後就按照自己的想法寫了個,功能和百度魔拍類似。

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


apk下載地址:http://home.ustc.edu.cn/~voa/res/HelloJni.apk

2.原理

繼承自view類,override其onDraw函式,把兩個背景圖(一個灰的一個紅的)和一個開關圖(圓開關)通過canvas畫出來;同時override其onTouchEvent函式,實現滑動效果;最後開啟一個執行緒做動畫,實現緩慢滑動的效果。

3. 程式碼

//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 Viewpublic 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 = 0private int mBmpHeight = 0private int mThumbWidth = 0private  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, null, mSwitch_off);   drawBitmap(canvas, null, null, mSwitch_thumb);   mPaint.setColor(Color.rgb(105, 105, 105));   canvas.translate(mSwitch_thumb.getWidth(), 0);   canvas.drawText(mOffText, 0, 20, mPaint);  }  else if(mSwitchStatus == SWITCH_ON)  {   drawBitmap(canvas, null, null, mSwitch_on);   int count = canvas.save();   canvas.translate(mSwitch_on.getWidth() - mSwitch_thumb.getWidth(), 0);   drawBitmap(canvas, null, null, mSwitch_thumb);   mPaint.setColor(Color.WHITE);   canvas.restoreToCount(count);   canvas.drawText(mOnText, 17, 20, mPaint);  }  else //SWITCH_SCROLING  {   mSwitchStatus = mDstX > 35 ? SWITCH_ON : SWITCH_OFF;   drawBitmap(canvas, new Rect(0, 0, mDstX, mBmpHeight), new Rect(0, 0, (int)mDstX, mBmpHeight), mSwitch_on);   mPaint.setColor(Color.WHITE);   canvas.drawText(mOnText, 17, 20, mPaint);   int count = canvas.save();   canvas.translate(mDstX, 0);   drawBitmap(canvas, new Rect(mDstX, 0, mBmpWidth, mBmpHeight),                          new Rect(0, 0, mBmpWidth - mDstX, mBmpHeight), mSwitch_off);   canvas.restoreToCount(count);   count = canvas.save();   canvas.clipRect(mDstX, 0, mBmpWidth, mBmpHeight);   canvas.translate(mThumbWidth, 0);   mPaint.setColor(Color.rgb(105, 105, 105));   canvas.drawText(mOffText, 0, 20, mPaint);   canvas.restoreToCount(count);   count = canvas.save();   canvas.translate(mDstX - mThumbWidth / 2, 0);   drawBitmap(canvas, null, null, mSwitch_thumb);   canvas.restoreToCount(count);  } } public void drawBitmap(Canvas canvas, Rect src, Rect dst, Bitmap bitmap) {  dst = (dst == null ? new Rect(0, 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>
           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述