欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android自定義控件實現(xiàn)滑動開關(guān)效果

 更新時間:2016年07月22日 15:54:24   作者:sinat_29174099  
這篇文章主要為大家詳細介紹了Android自定義控件實現(xiàn)滑動開關(guān)效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了Android實現(xiàn)滑動開關(guān)效果的具體代碼,供大家參考,具體內(nèi)容如下

自定義開關(guān)控件

Android自定義控件一般有三種方式

1、繼承Android固有的控件,在Android原生控件的基礎(chǔ)上,進行添加功能和邏輯。
2、繼承ViewGroup,這類自定義控件是可以往自己的布局里面添加其他的子控件的。
3、繼承View,這類自定義控件沒有跟原生的控件有太多的相似的地方,也不需要在自己的肚子里添加其他的子控件。

ToggleView自定義開關(guān)控件表征上沒有跟Android原生的控件有什么相似的地方,而且在滑動的效果上也沒有沿襲Android原生的地方,所以我們的自定義ToggleView選擇繼承View

 同樣的自定義控件需要復寫三個構(gòu)造方法

//在布局中使用該控件的時候,而且有額外的style屬性的時候調(diào)用該構(gòu)造方法,
public ToggleView(Context context, AttributeSet attrs, int defStyle);
//在布局中使用該控件的時候調(diào)用該構(gòu)造方法
public ToggleView(Context context, AttributeSet attrs)
//在Java代碼中直接new該控件的時候,調(diào)用該構(gòu)造方法
public ToggleView(Context context)

因為是自定義的控件,所以屬性還是自己定義的比較好用一些。我們這里定義三個屬性

1、背景圖片
2、滑塊的圖片
3、布局中默認的開關(guān)的狀態(tài)

所以就需要用到了自定義屬性
在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表示屬性類型

這里定義了三個屬性名和屬性類型。

屬性和自定義控件的三個構(gòu)造方法已經(jīng)完成,就我們就可以在布局文件中添加自定義的控件了

<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里面的屬性了

可以直接使用自定義的屬性之后,問題應(yīng)該聚焦到怎么在Java代碼中獲取到我自定義的屬性的值呢?

根據(jù)命名空間和自定義屬性的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);

看到?jīng)]?該方法用到了attr參數(shù),所以獲取自定義屬性值的操作應(yīng)該在兩個參數(shù)的那里面執(zhí)行。

整體的自定義控件的類見代碼:

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;

/**
 * 自定義開關(guān)控件
 * @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;

 // 構(gòu)造方法,在xml文件布局的時候,指定了style的時候調(diào)用
 public ToggleView(Context context, AttributeSet attrs, int defStyle) {
 super(context, attrs, defStyle);
 }

 // 構(gòu)造方法,在xml文件中布局的時候,沒有指定style的時候調(diào)用
 public ToggleView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 //在Java代碼中 獲取到xml中自定義屬性對應(yīng)的值
 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);
 Log.i(TAG,""+toggle_slidingbackground+" "+toggle_switchbackground);
 // 設(shè)置自定義開關(guān)的圖片
 setToggleSwitchBackground(toggle_switchbackground);
 setToggleSlidingBackground(toggle_slidingbackground);
 setToggleState(toggle_state);
 }

 // 構(gòu)造方法 在代碼中new的時候調(diào)用
 public ToggleView(Context context) {
 this(context, null);

 }

 /**
 * 給滑動的控件設(shè)置背景圖片
 * 
 * @param toggle_slidingbackground 圖片ID
 */
 private void setToggleSlidingBackground(int toggle_slidingbackground) {
 sliding_background = BitmapFactory.decodeResource(getResources(),toggle_slidingbackground);
 }

 /**
 * 給背景的控件,設(shè)置背景圖片
 * 
 * @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) {
 //測量控件的大小,設(shè)置控件的大小為背景圖片的大小
 setMeasuredDimension(switch_background.getWidth(),switch_background.getHeight());
 }

 @Override
 protected void onDraw(Canvas canvas) {
 //開始畫自定義控件,使用canvas對象先把背景圖片畫上來
 canvas.drawBitmap(switch_background, 0, 0, null);
 if (isSliding) {
 //如果是滑動狀態(tài)
 //控件距離左邊的相對距離為:(控件每時每刻的距離自己左上方的焦點的x軸距離)-(控件本身一半的x軸寬度)
 int left = downX - sliding_background.getWidth() / 2;
 //控件最大的滑動距離(距離左邊最大的距離)就是:(背景圖片的寬度)-(滑塊圖片的寬度)
 int rightAlign = switch_background.getWidth()- sliding_background.getWidth();
 //如果距離左邊的距離小于0,,就不讓他繼續(xù)往左邊動了
 if (left < 0) {
 left = 0;
 } else if (left > rightAlign) {
 //如果距離左邊的距離》應(yīng)該距離左邊的最大距離,也不讓他往右邊移動了
 left = rightAlign;
 }
 //控制好屬性之后就可以時時刻刻的跟著畫了
 canvas.drawBitmap(sliding_background, left, 0, null);
 } else {
 //如果不滑動,則根據(jù)控件的屬性中開關(guān)的狀態(tài),來畫滑塊的位置
 if (toggle_state) {
 //如果開關(guān)狀態(tài)為真,滑塊移動到最右邊
 int left = switch_background.getWidth() - sliding_background.getWidth();
 canvas.drawBitmap(sliding_background, left, 0, null);
 } else {
 //如果開關(guān)狀態(tài)為假,滑塊移動到最左邊
 canvas.drawBitmap(sliding_background, 0, 0, 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:
 //當點擊結(jié)束的時候?qū)⑹欠窕瑒佑洖榧?,獲取到移動的x軸的坐標
 downX = (int) event.getX();
 isSliding = false;
 //獲取到背景圖片中間的那個值
 int center = switch_background.getWidth() / 2;

 boolean state = downX > center;
 //如果先后的狀態(tài)不相同,則將新的狀態(tài)賦給成員變量,然后調(diào)用監(jiān)聽的方法
 if (toggle_state != state) {
 toggle_state = state;
 if (null != mToggleStateChangeListener) {
  mToggleStateChangeListener
  .onToggleState(toggle_state);
 }
 }
 break;
 }
 //調(diào)用一次onDraw()方法
 invalidate();
 return true;
 }
 //給自定義開關(guān)控件設(shè)置監(jiān)聽的方法
 public void setOnToggleStateLinstener(OnToggleStateChangeListener listen){
 mToggleStateChangeListener = listen;

 }
 public void setToggleState(boolean b) {
 toggle_state = b;
 }
 //監(jiān)聽回調(diào)接口,方法由實現(xiàn)接口的類實現(xiàn)
 public interface OnToggleStateChangeListener {

 public void onToggleState(boolean state);
 }
}

到此,我們的自定義控件部分的邏輯就寫完了,借下來再MainActivity中調(diào)用一下

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);
 }
 });
 }


 //這里調(diào)用到的自己封裝的一個快速彈Toast的工具類
 private void showToast(boolean state) {
 ToastUtil.makeSuddenlyToast(getApplicationContext(), state?"開":"關(guān)");
 }
}

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;

 /**
 * 彈出短時間Toast
 * @param context 上下文對象
 * @param text 要彈出的文字
 */
 public static void makeShortToast(Context context,String text){
 toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
 toast.show();
 }

 /**
 * 彈出長時間的Toast
 * @param context 上下文對象
 * @param text 要彈出的文字
 */
 public static void makeLongToast(Context context,String text){
 toast = Toast.makeText(context, text, Toast.LENGTH_LONG);
 toast.show();
 }
 /**
 * 單例Toast
 * @param context 上下文對象
 * @param text 要彈出的文字
 */
 public static void makeSuddenlyToast(Context context,String text){
 if(toast==null){
 toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);
 }
 toast.setText(text);
 toast.show();
 }
}

總結(jié)一下,其實本次自定義控件的步驟如下:

1、在values/attrs.xml自定義屬性和屬性值的數(shù)據(jù)類型
2、在Java代碼中定義自定義控件類,繼承View或者ViewGroup或者Android原生的控件,實現(xiàn)構(gòu)造方法,獲取到自定義屬性的值,并且編寫對應(yīng)的邏輯和點擊事件。
3、在布局文件中使用自定義控件和自定義屬性(注意命名空間)。
4、在MainActivity中調(diào)用

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論