溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果

發(fā)布時間:2021-06-30 12:39:12 來源:億速云 閱讀:500 作者:小新 欄目:移動開發(fā)

這篇文章主要介紹了Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

一、效果圖

Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果 

二、RippleDrawable基本概念介紹

(1)、RippleDrawable

RippleDrawable可以實現(xiàn)上面效果圖中的水波紋效果,它是在API 21 中添加的,所以,低于21的版本中不可使用。它的繼承關(guān)系如下:

Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果

根據(jù)上面的繼承關(guān)系,我們可知,我們可以用它來做背景;RippleDrawable是有層級的——LayerDrawable的特性。

(2)、xml屬性

RippleDrawable在xml中對應(yīng)的是 <ripple></ripple>,它只有兩個屬性——color、radius。具體可參考下圖:

Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果 

(3)、ripple的特性

A touch feedback drawable may contain multiple child layers, including a special mask layer that is not drawn to the screen. A single layer may be set as the mask from XML by specifying its android:id value as [R.id.mask](https://developer.android.com/reference/android/R.id.html#mask) . At run time, a single layer may be set as the mask using setId(..., android.R.id.mask) or an existing mask layer may be replaced using setDrawableByLayerId(android.R.id.mask, ...) .

ripple可以對觸摸事件作出相應(yīng)的反饋,它可以包含多個item。

其中id 為 mask 的item 在初始化界面時不會直接繪制出來,而是在發(fā)生觸摸之后才會繪制。

mask 直譯過來有遮罩的意思,它會限定水波紋的范圍。

如果我們需要將 ripple 中的某個item設(shè)置為 mask , 在xml 中,直接為該item設(shè)置id屬性即可—— android:id="@android:id/mask" ; 在Java代碼中如果想替換現(xiàn)有的mask,可以通過 RippleDrawable中的 setDrawableByLayerId(android.R.id.mask, newDrawable) 來實現(xiàn)。

沒有指定mask ,并且也沒有指定radius 時,會以控件寬高中的較大值為直徑繪制水波紋,這樣就必然會超出控件的范圍,所以,這種效果也叫做 無界水波紋效果。

指定mask 后 ,id 為 mask 的item 中指定的drawable 可以限定水波紋的范圍。

 三、代碼示例:

(1)、xml 中定義 ripple

下列代碼依次對應(yīng)效果圖中的前6個。

ripple_1.xml

<?xml version="1.0" encoding="utf-8"?>

<!--只有一個 ripple 節(jié)點-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

</ripple>

ripple_2.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

  <!--為drawable 賦一個color 值,是不生效的-->
  <item
    android:id="@android:id/mask"
    android:drawable="@color/blue" />
</ripple>

ripple_3.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

  <!--這里使用drawable時,并不是所有drawable都生效。需要帶有透明邊框.否則,圖片不生效。而且,繪制出來之后會更改掉原圖的色彩信息,
  圖片的顏色值會變?yōu)?nbsp;ripple 節(jié)點中的 color 值;ripple 只會在該圖片區(qū)域內(nèi)有效;圖片會被拉伸-->
  <item
    android:id="@android:id/mask"
    android:drawable="@drawable/act_attentioned" />
  <!--android:drawable="@drawable/square_team_selected"/>-->
</ripple>

ripple_4.xml

<?xml version="1.0" encoding="utf-8"?>

<!--以此作為 backGround時,控件初始時使用 item 作為bg ; 按壓時會有一個色值漸變效果,按住不松時會顯示 ripple 和 item 中顏色的混合值;
松手的瞬間會顯示 ripple 中色值,然后再漸變?yōu)閕tem中的色值-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

  <item>
    <shape android:shape="rectangle">
      <solid android:color="@color/blue" />
      <corners android:radius="@dimen/dp10" />
    </shape>
  </item>

</ripple>

ripple_5.xml

<?xml version="1.0" encoding="utf-8"?>

<!--以此作為 backGround時,控件沒有默認(rèn)背景色;生效的只有ripple中的色值;此時,item 只要控制ripple 的范圍-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

  <item android:id="@android:id/mask">
    <shape android:shape="rectangle">
      <solid android:color="@color/blue" />
      <corners android:radius="@dimen/dp10" />
    </shape>
  </item>

</ripple>

ripple_6.xml

<?xml version="1.0" encoding="utf-8"?>

<!--相當(dāng)于 ripple 和 selector 的疊加-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:color="@color/colorAccent"
  tools:targetApi="lollipop">

  <item>
    <selector>
      <item
        android:drawable="@drawable/daomeixiong"
        android:state_pressed="true" />

      <item android:drawable="@drawable/gongfuxiongmao" />
    </selector>
  </item>
</ripple>

(2)、java代碼中定義ripple

下列代碼依次對應(yīng)效果圖中的后五個

/**
 * 作者:CnPeng
 * 時間:2018/8/8
 * 功用:Ripple使用示例
 * 其他:
 */
public class RippleDrawableActivity extends AppCompatActivity {
  ActivityRippleBinding mBinding;

  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mBinding = DataBindingUtil.setContentView(this, R.layout.activity_ripple);

    initTv1RippleBG(R.color.f9cf87);
    initTv2RippleBG();
    initTv3RippleBG();
    initTv4RippleBG();
    initTv5RippleBG();
  }

  /**
   * 作者:CnPeng
   * 時間:2018/8/8 下午3:37
   * 功用:xml中已經(jīng)設(shè)置背景為 ripple_1.xml 為背景,此處是更改ripple_1中的顏色
   * 說明:
   */
  @SuppressLint("ClickableViewAccessibility")
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  public void initTv1RippleBG(final int colorResId) {
    final RippleDrawable rippleDrawable = (RippleDrawable) mBinding.tvRippleBg1.getBackground();
    mBinding.tvRippleBg1.setOnTouchListener(new View.OnTouchListener() {
      @RequiresApi(api = Build.VERSION_CODES.M)
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        rippleDrawable.setHotspot(event.getX(), event.getY());
        //如果radius小于控件的寬高中的大值,則,觸摸超出radius的部分時,也只會在控件中心位置為起點以radius為半徑繪制ripple
        rippleDrawable.setRadius(200);
        rippleDrawable.setColor(ColorStateList.valueOf(getResources().getColor(colorResId)));
        return false;
      }
    });
  }

  /**
   * 作者:CnPeng
   * 時間:2018/8/8 下午12:02
   * 功用:以代碼的方式構(gòu)建rippleDrawable為背景——沒有設(shè)置mask
   * 說明:http://www.tothenew.com/blog/ripple-effect-in-android/
   * https://www.programcreek.com/java-api-examples/index.php?api=android.graphics.drawable.RippleDrawable
   */
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  private void initTv2RippleBG() {

    int[][] stateList = new int[][]{
        new int[]{android.R.attr.state_pressed},
        new int[]{android.R.attr.state_focused},
        new int[]{android.R.attr.state_activated},
        new int[]{}
    };

    //深藍(lán)
    int normalColor = Color.parseColor("#303F9F");
    //玫瑰紅
    int pressedColor = Color.parseColor("#FF4081");
    int[] stateColorList = new int[]{
        pressedColor,
        pressedColor,
        pressedColor,
        normalColor
    };
    ColorStateList colorStateList = new ColorStateList(stateList, stateColorList);

    RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, null);
    mBinding.tvRippleBg2.setBackground(rippleDrawable);
  }

  /**
   * 作者:CnPeng
   * 時間:2018/8/8 下午12:02
   * 功用:以代碼的方式構(gòu)建rippleDrawable為背景——有drawable,但不設(shè)置mask
   * 說明:http://www.tothenew.com/blog/ripple-effect-in-android/
   * https://www.programcreek.com/java-api-examples/index.php?api=android.graphics.drawable.RippleDrawable
   */
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  private void initTv3RippleBG() {

    int[][] stateList = new int[][]{
        new int[]{android.R.attr.state_pressed},
        new int[]{android.R.attr.state_focused},
        new int[]{android.R.attr.state_activated},
        new int[]{}
    };

    //深藍(lán)
    int normalColor = Color.parseColor("#303F9F");
    //玫瑰紅
    int pressedColor = Color.parseColor("#FF4081");
    int[] stateColorList = new int[]{
        pressedColor,
        pressedColor,
        pressedColor,
        normalColor
    };
    ColorStateList colorStateList = new ColorStateList(stateList, stateColorList);

    Drawable drawable = getResources().getDrawable(R.drawable.act_attentioned);
    RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, drawable, null);
    mBinding.tvRippleBg3.setBackground(rippleDrawable);
  }

  /**
   * 作者:CnPeng
   * 時間:2018/8/8 下午12:02
   * 功用:以代碼的方式構(gòu)建rippleDrawable為背景——無drawable,設(shè)置mask
   * 說明:http://www.tothenew.com/blog/ripple-effect-in-android/
   * https://www.programcreek.com/java-api-examples/index.php?api=android.graphics.drawable.RippleDrawable
   */
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  private void initTv4RippleBG() {

    int[][] stateList = new int[][]{
        new int[]{android.R.attr.state_pressed},
        new int[]{android.R.attr.state_focused},
        new int[]{android.R.attr.state_activated},
        new int[]{}
    };

    //深藍(lán)
    int normalColor = Color.parseColor("#303F9F");
    //玫瑰紅
    int pressedColor = Color.parseColor("#FF4081");
    int[] stateColorList = new int[]{
        pressedColor,
        pressedColor,
        pressedColor,
        normalColor
    };
    ColorStateList colorStateList = new ColorStateList(stateList, stateColorList);

    Drawable drawable = getResources().getDrawable(R.drawable.act_attentioned);
    RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, drawable);
    mBinding.tvRippleBg4.setBackground(rippleDrawable);
  }

  /**
   * 作者:CnPeng
   * 時間:2018/8/8 下午12:02
   * 功用:以代碼的方式構(gòu)建rippleDrawable為背景——有drawable,設(shè)置mask
   * 說明:http://www.tothenew.com/blog/ripple-effect-in-android/
   * https://www.programcreek.com/java-api-examples/index.php?api=android.graphics.drawable.RippleDrawable
   */
  @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
  private void initTv5RippleBG() {

    int[][] stateList = new int[][]{
        new int[]{android.R.attr.state_pressed},
        new int[]{android.R.attr.state_focused},
        new int[]{android.R.attr.state_activated},
        new int[]{}
    };

    //深藍(lán)
    int normalColor = Color.parseColor("#303F9F");
    //玫瑰紅
    int pressedColor = Color.parseColor("#FF4081");
    int[] stateColorList = new int[]{
        pressedColor,
        pressedColor,
        pressedColor,
        normalColor
    };
    ColorStateList colorStateList = new ColorStateList(stateList, stateColorList);

    float[] outRadius = new float[]{10, 10, 15, 15, 20, 20, 25, 25};
    RoundRectShape roundRectShape = new RoundRectShape(outRadius, null, null);
    ShapeDrawable maskDrawable = new ShapeDrawable();
    maskDrawable.setShape(roundRectShape);
    maskDrawable.getPaint().setColor(Color.parseColor("#000000"));
    maskDrawable.getPaint().setStyle(Paint.Style.FILL);

    ShapeDrawable contentDrawable = new ShapeDrawable();
    contentDrawable.setShape(roundRectShape);
    contentDrawable.getPaint().setColor(Color.parseColor("#f7c653"));
    contentDrawable.getPaint().setStyle(Paint.Style.FILL);

    //contentDrawable實際是默認(rèn)初始化時展示的;maskDrawable 控制了rippleDrawable的范圍
    RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, contentDrawable, maskDrawable);
    mBinding.tvRippleBg5.setBackground(rippleDrawable);
  }
}

(3)、activity_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<layout>

  <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:orientation="vertical">

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center_horizontal"
      android:orientation="vertical"
      android:padding="@dimen/dp10">

      <!--無界水波紋效果,所謂無界,實際是以空間寬度或高度中的大值作為直徑繪制一個園-->
      <TextView
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:background="@drawable/ripple_1"
        android:clickable="true"
        android:gravity="center"
        android:text="不設(shè)置mask/wrapContent" />

      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/ripple_1"
        android:clickable="true"
        android:gravity="center"
        android:text="不設(shè)置mask/match_parent" />

      <!--有界水波紋效果。水波紋效果只在控件內(nèi)繪制-->
      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/ripple_2"
        android:clickable="true"
        android:gravity="center"
        android:text="mask/match_parent/drawable_color" />

      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/ripple_3"
        android:clickable="true"
        android:gravity="center"
        android:text="mask/match_parent/drawable_drawable" />

      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@drawable/ripple_4"
        android:clickable="true"
        android:gravity="center"
        android:text="match_parent/drawable_shape" />

      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:background="@drawable/ripple_5"
        android:clickable="true"
        android:gravity="center"
        android:text="match_parent/drawable_shape" />

      <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:background="@drawable/ripple_6"
        android:clickable="true"
        android:gravity="center"
        android:text="match_parent/drawable_shape" />


      <!--測試代碼控制ripple顏色-->
      <TextView
        android:id="@+id/tv_rippleBg1"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:background="@drawable/ripple_1"
        android:clickable="true"
        android:gravity="center"
        android:text="代碼控制更改ripple.xml中的顏色" />

      <!--測試代碼控制ripple顏色-->
      <TextView
        android:id="@+id/tv_rippleBg2"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:clickable="true"
        android:gravity="center"
        android:text="代碼編寫ripple作為Tv背景_無derawable_無mask" />

      <!--測試代碼控制ripple顏色-->
      <TextView
        android:id="@+id/tv_rippleBg3"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:clickable="true"
        android:gravity="center"
        android:text="代碼控制ripple3_有drawable_無mask" />

      <!--測試代碼控制ripple顏色-->
      <TextView
        android:id="@+id/tv_rippleBg4"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:clickable="true"
        android:gravity="center"
        android:text="代碼控制ripple4_無drawable_有mask" />

      <!--測試代碼控制ripple顏色-->
      <TextView
        android:id="@+id/tv_rippleBg5"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="@dimen/dp10"
        android:clickable="true"
        android:gravity="center"
        android:text="代碼控制ripple5_有drawable_有mask" />
    </LinearLayout>
  </ScrollView>
</layout>

四、總結(jié)

(1)、漣漪效果的應(yīng)用現(xiàn)狀


應(yīng)用名稱是否應(yīng)用漣漪效果應(yīng)用的位置
知乎在底部導(dǎo)航和首頁列表中有應(yīng)用
QQ
微信
簡書
支付寶
口碑
微博
美團(tuán)
淘寶消息列表和Dialog中的按鈕

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Android RippleDrawable如何實現(xiàn)水波紋/漣漪效果”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI