每天都被不同的需求糾纏的生活是幸福而又不幸的,這不我們家親愛的設計師們又讓我們在低版本的 Android 平台上實現一下類似於 Material Design 的點擊效果。
雖然大家都知道 MaterialDesign 的確好看很多,但是讓我們為低版本適配也是一個苦逼的活兒。
不過還好,在使用了 nineoldandroids 這個開源庫之后,總算是實現了這個效果。
先放出一個 Github 地址,大家如果可以去那里看看源碼: https://github.com/Kifile/MaterialView, 能夠 Star 一下就更好了。
再給出兩張效果圖,分別是基於 TextView 和 ImageView 的點擊效果:
圖1 TextView、ImageView應用后的點擊效果示意圖
1.代碼實現邏輯
首先我們分析一下這種點擊效果的實現邏輯。
點擊效果的處理主要分為兩個階段:
a.手指按下:
當用戶觸摸到控件的時候,首先我們先讓控件顯示一層淺色遮罩,然后從手指按下位置開始,有一個深色遮罩逐漸擴大至整個控件。
b.手指彈起:
當用戶松開手指之后,這里存在兩種情況,一種是深色遮罩已經擴大到了整個控件的范圍,一種是深色遮罩尚未完全包圍整個控件。
對於前一種情況,我們簡單做一次透明度變化,讓遮罩逐漸消失即可;
對於后一種情況,我們需要讓深色遮罩從當前的位置快速擴散到整個控件,同時也要做透明度變化,放置遮罩消失太過突兀。
具體代碼實現邏輯請參看這里: https://github.com/Kifile/MaterialView/blob/master/materialwidget/src/main/java/com/kifile/materialwidget/MaterialBackgroundDetector.java,MaterialBackgroundDetector 中 onTouchEvent 的處理。
2.使用庫文件實現 Material 點擊效果
目前我已經將這個項目部署到了 Maven 中心庫中,如果大家對部署的邏輯感興趣,可以看看這篇文章(一步一步教你分享開源項目到 Maven 中心倉庫),因此如果大家是使用 Android Studio 來開發項目,可以通過使用以下代碼將本庫進行集成:
- dependencies {
- compile 'com.kifile:MaterialView:1.0'
- }
通過在 gradle.build 文件中引入 maven 項目,我們現在就可以正式使用這個點擊效果了。
a.繼承你希望實現的控件,代碼如下:
- public class MaterialImageView extends ImageView {
- public MaterialImageView(Context context) {
- super(context);
- init(null, 0);
- }
- public MaterialImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init(attrs, 0);
- }
- public MaterialImageView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init(attrs, defStyle);
- }
- }
b.在 init 方法中創建一個 MaterialBackgroundDetector 對象,用於事件委托:
- private MaterialBackgroundDetector mDetector;
- private void init(AttributeSet attrs, int defStyle) {
- final TypedArray a = getContext().obtainStyledAttributes(
- attrs, com.kifile.materialwidget.R.styleable.MaterialTextView, defStyle, 0);
- int color = a.getColor(com.kifile.materialwidget.R.styleable.MaterialTextView_maskColor, MaterialBackgroundDetector.DEFAULT_COLOR);
- a.recycle();
- mDetector = new MaterialBackgroundDetector(getContext(), this, null, color);
- }
c.重寫父類方法,將相應事件委托給 mDetector 對象處理
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mDetector.onSizeChanged(w, h);
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- boolean superResult = super.onTouchEvent(event);
- return mDetector.onTouchEvent(event, superResult);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (isInEditMode()) {
- return;
- }
- mDetector.draw(canvas);
- }
d.(可選)將點擊事件的處理也交給 mDetector
當我們對控件進行點擊的時候,android 自身的點擊事件處理機制會起作用,如果你的點擊回調函數中存在頁面跳轉,那么你可能會發現,當你進行點擊之后,按鍵中深色遮罩尚未擴散到整個控件,整個界面就已經跳轉。這樣會導致Material 動畫看起來會在跳轉的一剎那停止。
為了解決這種問題,我們需要在繼承的空間中對點擊事件做處理,我們先讓 mDetector 接收到點擊請求,當動畫執行完畢之后,再進行分發給控件做點擊處理。
因此,你需要實現以下代碼:
1)在 init 方法里,將 null,改為 this,令控件實現Callback接口
- mDetector = new MaterialBackgroundDetector(getContext(), this, this, color);
2)重寫以下方法:
- @Override
- public boolean performClick() {
- return mDetector.handlePerformClick();
- }
- @Override
- public boolean performLongClick() {
- return mDetector.handlePerformLongClick();
- }
- @Override
- public void performClickAfterAnimation() {
- super.performClick();
- }
- @Override
- public void performLongClickAfterAnimation() {
- super.performLongClick();
- }
到目前為止,你已經成功的完成了整個界面效果的實現,恭喜你!
3.關於混淆
其實很多時候,我們都可能涉及到對代碼進行混淆,為了避免在混淆過程中,混淆工具對代碼的處理導致程序應用失敗,我們需要在混淆配置文件中加入以下代碼:
- -keep class com.kifile.materialwidget.MaterialBackgroundDetector {
- public void setRadius(...);
- public void setAlpha(...);
- }
基本上整個代碼的使用流程就到這里了,感謝大家的閱覽,如果覺得對自己有幫助,還請頂一下。
其他精彩文章文章
jQuery教程(10)-DOM樹操作之內容setter和getter方法
android學習筆記(37)使用 DatePickerDialog、TimePickerDialog
更多關於android開發文章