国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android自定義控件實(shí)現(xiàn)滑動(dòng)開(kāi)關(guān)效果

2019-12-12 05:54:53
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

 

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

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

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

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

因?yàn)槭亲远x的控件,所以屬性還是自己定義的比較好用一些。我們這里定義三個(gè)屬性
1、背景圖片
2、滑塊的圖片
3、布局中默認(rèn)的開(kāi)關(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>標(biāo)簽中,一個(gè)標(biāo)簽寫(xiě)一個(gè)屬性 name屬性表示屬性名稱,format表示屬性類型

這里定義了三個(gè)屬性名和屬性類型。

屬性和自定義控件的三個(gè)構(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開(kāi)頭的,部分屬性是以hss(我自己定義的命名空間)開(kāi)頭的,這是為什么呢?

注意看本片代碼第二行,

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

我在這里寫(xiě)著樣一行代碼,就說(shuō)明把values/attrs.xml中的每個(gè)條目都導(dǎo)入進(jìn)來(lái)了,就可以直接使用我在attrs.xml里面的屬性了

可以直接使用自定義的屬性之后,問(wèn)題應(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)該在兩個(gè)參數(shù)的那里面執(zhí)行。

整體的自定義控件的類見(jiàn)代碼:

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;/** * 自定義開(kāi)關(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文件布局的時(shí)候,指定了style的時(shí)候調(diào)用 public ToggleView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle); } // 構(gòu)造方法,在xml文件中布局的時(shí)候,沒(méi)有指定style的時(shí)候調(diào)用 public ToggleView(Context context, AttributeSet attrs) {  this(context, attrs, 0);  //在Java代碼中 獲取到xml中自定義屬性對(duì)應(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è)置自定義開(kāi)關(guān)的圖片  setToggleSwitchBackground(toggle_switchbackground);  setToggleSlidingBackground(toggle_slidingbackground);  setToggleState(toggle_state); } // 構(gòu)造方法 在代碼中new的時(shí)候調(diào)用 public ToggleView(Context context) {  this(context, null); } /**  * 給滑動(dòng)的控件設(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) {  //測(cè)量控件的大小,設(shè)置控件的大小為背景圖片的大小  setMeasuredDimension(switch_background.getWidth(),switch_background.getHeight()); } @Override protected void onDraw(Canvas canvas) {  //開(kāi)始畫(huà)自定義控件,使用canvas對(duì)象先把背景圖片畫(huà)上來(lái)  canvas.drawBitmap(switch_background, 0, 0, null);  if (isSliding) {  //如果是滑動(dòng)狀態(tài)   //控件距離左邊的相對(duì)距離為:(控件每時(shí)每刻的距離自己左上方的焦點(diǎn)的x軸距離)-(控件本身一半的x軸寬度)   int left = downX - sliding_background.getWidth() / 2;   //控件最大的滑動(dòng)距離(距離左邊最大的距離)就是:(背景圖片的寬度)-(滑塊圖片的寬度)   int rightAlign = switch_background.getWidth()- sliding_background.getWidth();   //如果距離左邊的距離小于0,,就不讓他繼續(xù)往左邊動(dòng)了   if (left < 0) {    left = 0;   } else if (left > rightAlign) {    //如果距離左邊的距離》應(yīng)該距離左邊的最大距離,也不讓他往右邊移動(dòng)了    left = rightAlign;   }   //控制好屬性之后就可以時(shí)時(shí)刻刻的跟著畫(huà)了   canvas.drawBitmap(sliding_background, left, 0, null);  } else {   //如果不滑動(dòng),則根據(jù)控件的屬性中開(kāi)關(guān)的狀態(tài),來(lái)畫(huà)滑塊的位置   if (toggle_state) {    //如果開(kāi)關(guān)狀態(tài)為真,滑塊移動(dòng)到最右邊    int left = switch_background.getWidth() - sliding_background.getWidth();    canvas.drawBitmap(sliding_background, left, 0, null);   } else {    //如果開(kāi)關(guān)狀態(tài)為假,滑塊移動(dòng)到最左邊    canvas.drawBitmap(sliding_background, 0, 0, null);   }  }  super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) {  //重寫(xiě)觸摸事件  int action = event.getAction();  switch (action) {  case MotionEvent.ACTION_DOWN:   //開(kāi)始點(diǎn)擊的時(shí)候,是否滑動(dòng)置為真,獲取到當(dāng)前手指的距離   isSliding = true;   downX = (int) event.getX();   break;  case MotionEvent.ACTION_MOVE:   downX = (int) event.getX();   break;  case MotionEvent.ACTION_UP:   //當(dāng)點(diǎn)擊結(jié)束的時(shí)候?qū)⑹欠窕瑒?dòng)記為假,獲取到移動(dòng)的x軸的坐標(biāo)   downX = (int) event.getX();   isSliding = false;   //獲取到背景圖片中間的那個(gè)值   int center = switch_background.getWidth() / 2;   boolean state = downX > center;   //如果先后的狀態(tài)不相同,則將新的狀態(tài)賦給成員變量,然后調(diào)用監(jiān)聽(tīng)的方法   if (toggle_state != state) {    toggle_state = state;    if (null != mToggleStateChangeListener) {     mToggleStateChangeListener       .onToggleState(toggle_state);    }   }   break;  }  //調(diào)用一次onDraw()方法  invalidate();  return true; } //給自定義開(kāi)關(guān)控件設(shè)置監(jiān)聽(tīng)的方法 public void setOnToggleStateLinstener(OnToggleStateChangeListener listen){  mToggleStateChangeListener = listen; } public void setToggleState(boolean b) {  toggle_state = b; } //監(jiān)聽(tīng)回調(diào)接口,方法由實(shí)現(xiàn)接口的類實(shí)現(xiàn) public interface OnToggleStateChangeListener {  public void onToggleState(boolean state); }}

到此,我們的自定義控件部分的邏輯就寫(xiě)完了,,借下來(lái)再M(fèi)ainActivity中調(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)用到的自己封裝的一個(gè)快速?gòu)桾oast的工具類 private void showToast(boolean state) {  ToastUtil.makeSuddenlyToast(getApplicationContext(), state?"開(kāi)":"關(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; /**  * 彈出短時(shí)間Toast  * @param context 上下文對(duì)象  * @param text 要彈出的文字  */ public static void makeShortToast(Context context,String text){  toast = Toast.makeText(context, text, Toast.LENGTH_SHORT);  toast.show(); } /**  * 彈出長(zhǎng)時(shí)間的Toast  * @param context 上下文對(duì)象  * @param text 要彈出的文字  */ public static void makeLongToast(Context context,String text){  toast = Toast.makeText(context, text, Toast.LENGTH_LONG);  toast.show(); } /**  * 單例Toast  * @param context 上下文對(duì)象  * @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é)一下,其實(shí)本次自定義控件的步驟如下:
1、在values/attrs.xml自定義屬性和屬性值的數(shù)據(jù)類型
2、在Java代碼中定義自定義控件類,繼承View或者ViewGroup或者Android原生的控件,實(shí)現(xiàn)構(gòu)造方法,獲取到自定義屬性的值,并且編寫(xiě)對(duì)應(yīng)的邏輯和點(diǎn)擊事件。
3、在布局文件中使用自定義控件和自定義屬性(注意命名空間)。
4、在MainActivity中調(diào)用

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 拉萨市| 西乌| 通化县| 土默特左旗| 吉木萨尔县| 葫芦岛市| 长海县| 西充县| 淳化县| 盐源县| 五大连池市| 泽库县| 瑞安市| 绥德县| 涞水县| 武定县| 新化县| 方正县| 泸州市| 肃宁县| 曲沃县| 肥东县| 仙居县| 娱乐| 郁南县| 南宫市| 沙田区| 金乡县| 乌审旗| 太原市| 嘉义县| 南京市| 阿勒泰市| 宽城| 梓潼县| 灵山县| 孟连| 博客| 新民市| 宁强县| 芒康县|