【Android】自訂控制項實現可滑動的開關(switch),androidswitch

來源:互聯網
上載者:User

【Android】自訂控制項實現可滑動的開關(switch),androidswitch

~轉載請註明來源:http://blog.csdn.net/u013015161/article/details/46704745

介紹

昨天晚上寫了一個Android的滑動開關, 即SlideSwitch。效果如下:

實現

實現的思路其實很簡單,監聽控制項上的touch事件,並不斷重新整理,讓滑塊在手指的位置上繪出,達到滑塊跟著手指滑動的顯示效果。
先看一下代碼:
SlideSwitch.java (7月3日有修改:在touch事件裡調用onStateChangedListener前增加判空)

package com.incell.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;public class SlideSwitch extends View{    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //消除鋸齒    boolean isOn = false;    float curX = 0;    float centerY; //y固定    float viewWidth;    float radius;    float lineStart; //直線段開始的位置(橫座標,即    float lineEnd; //直線段結束的位置(縱座標    float lineWidth;    final int SCALE = 4; // 控制項長度為滑動的圓的半徑的倍數    OnStateChangedListener onStateChangedListener;    public SlideSwitch(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public SlideSwitch(Context context, AttributeSet attrs) {        super(context, attrs);    }    public SlideSwitch(Context context) {        super(context);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        // TODO Auto-generated method stub        curX = event.getX();        if(event.getAction() == MotionEvent.ACTION_UP)        {            if(curX > viewWidth / 2)            {                curX = lineEnd;                if(false == isOn)                {                    //只有狀態發生改變才調用回呼函數, 下同                    if(null != onStateChangedListener)                    {                        onStateChangedListener.onStateChanged(true);                    }                    isOn = true;                }            }            else            {                curX = lineStart;                if(true == isOn)                {                    if(null != onStateChangedListener)                    {                        onStateChangedListener.onStateChanged(false);                    }                    isOn = false;                }            }        }        /*通過重新整理調用onDraw*/        this.postInvalidate();        return true;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // TODO Auto-generated method stub        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        /*保持寬是高的SCALE / 2倍, 即圓的直徑*/        this.setMeasuredDimension(this.getMeasuredWidth(), this.getMeasuredWidth() * 2 / SCALE);        viewWidth = this.getMeasuredWidth();        radius = viewWidth / SCALE;        lineWidth = radius * 2f; //直線寬度等於滑塊直徑        curX = radius;        centerY = this.getMeasuredWidth() / SCALE; //centerY為高度的一半        lineStart = radius;        lineEnd = (SCALE - 1) * radius;    }    @Override    protected void onDraw(Canvas canvas) {        // TODO Auto-generated method stub        super.onDraw(canvas);        /*限制滑動範圍*/        curX = curX > lineEnd?lineEnd:curX;        curX = curX < lineStart?lineStart:curX;        /*劃線*/        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(lineWidth);        /*左邊部分的線,綠色*/        mPaint.setColor(Color.BLUE);        canvas.drawLine(lineStart, centerY, curX, centerY, mPaint);        /*右邊部分的線,灰色*/        mPaint.setColor(Color.GRAY);        canvas.drawLine(curX, centerY, lineEnd, centerY, mPaint);        /*畫圓*/        /*畫最左和最右的圓,直徑為直線段寬度, 即在直線段兩邊分別再加上一個半圓*/        mPaint.setStyle(Paint.Style.FILL);        mPaint.setColor(Color.GRAY);        canvas.drawCircle(lineEnd, centerY, lineWidth / 2, mPaint);          mPaint.setColor(Color.BLUE);        canvas.drawCircle(lineStart, centerY, lineWidth / 2, mPaint);        /*圓形滑塊*/        mPaint.setColor(Color.LTGRAY);        canvas.drawCircle(curX, centerY, radius , mPaint);    }    /*設定開關狀態改變監聽器*/    public void setOnStateChangedListener(OnStateChangedListener o)    {        this.onStateChangedListener = o;    }    /*內部介面,開關狀態改變監聽器*/    public interface OnStateChangedListener    {        public void onStateChanged(boolean state);    }}

注釋應該很詳細了。主要有以下幾點。
1、重寫了onMeasure方法,使控制項高度依賴於控制項的寬度。這樣不論在布局檔案中如何設定,總能保證控制項的寬高比
2、控制好滑塊的活動範圍
3、定義內部介面OnStateChangedListener,並在自訂控制項裡定義了其對象以及從外部賦值的方法setOnStateChangedListener,以便對開關狀態變更事件進行監聽並調用回調

使用及Demo

在布局檔案中添加該控制項即可使用。Demo效果為動圖展示效果(demo裡顏色為綠色,動圖為藍色是因為綠色會導致截取gif時出問題,臨時更改的)。
Demo中布局檔案如下:
activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.example.slideswitchexample.SlideSwitch        android:id="@+id/slide_switch"        android:layout_width="200dp"        android:layout_height="wrap_content"        android:layout_centerInParent="true"/></RelativeLayout>

Demo中Activity代碼如下:
MainActivity.java

package com.example.slideswitchexample;import com.example.slideswitchexample.SlideSwitch.OnStateChangedListener;import android.app.Activity;import android.os.Bundle;import android.widget.Toast;public class MainActivity extends Activity {    SlideSwitch sSwitch;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        sSwitch = (SlideSwitch) this.findViewById(R.id.slide_switch);        sSwitch.setOnStateChangedListener(new OnStateChangedListener(){            @Override            public void onStateChanged(boolean state) {                // TODO Auto-generated method stub                if(true == state)                {                    Toast.makeText(MainActivity.this, "開關已開啟", 1000).show();                }                else                {                    Toast.makeText(MainActivity.this, "開關已關閉", 1000).show();                }            }        });    }}

點此下載Demo工程

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.