一宴偿、效果圖
二、RippleDrawable基本概念介紹
(1)、RippleDrawable
RippleDrawable可以實現(xiàn)上面效果圖中的水波紋效果迫肖,它是在API 21 中添加的拷呆,所以闲坎,低于21的版本中不可使用。它的繼承關(guān)系如下:
根據(jù)上面的繼承關(guān)系茬斧,我們可知腰懂,我們可以用它來做背景;RippleDrawable是有層級的——LayerDrawable的特性项秉。
(2)绣溜、xml屬性
RippleDrawable在xml中對應(yīng)的是 <ripple></ripple>,它只有兩個屬性——color、radius娄蔼。具體可參考下圖:
(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 usingsetId(..., android.R.id.mask)
or an existing mask layer may be replaced usingsetDrawableByLayerId(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)?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)用 |
無 | 無 | |
微信 | 無 | 無 |
簡書 | 無 | 無 |
支付寶 | 無 | 無 |
口碑 | 無 | 無 |
微博 | 無 | 無 |
美團(tuán) | 無 | 無 |
淘寶 | 有 | 消息列表和Dialog中的按鈕 |
在查看了我自己常用的幾款軟件之后,發(fā)現(xiàn)讯蒲,只有知乎和淘寶在局部使用了這個漣漪效果痊土,這。墨林。赁酝。似乎有點尷尬啊
(2)、參考文章:
http://www.tothenew.com/blog/ripple-effect-in-android/
https://developer.android.com/reference/android/graphics/drawable/RippleDrawable
(3)旭等、代碼地址
文中代碼地址為:https://github.com/CnPeng/CnPengAndroid.git
文中內(nèi)容對應(yīng)其中的:b_35_rippleDrawable 文件夾
本文到此結(jié)束酌呆,謝謝觀看!
如有不足搔耕,敬請指正隙袁!