1. 程式人生 > >讓低版本的 Android 專案顯示出 Material 風格的點選效果

讓低版本的 Android 專案顯示出 Material 風格的點選效果

 

      每天都被不同的需求糾纏的生活是幸福而又不幸的,這不我們家親愛的設計師們又讓我們在低版本的 Android 平臺上實現一下類似於 Material Design 的點選效果。

       雖然大家都知道 MaterialDesign 的確好看很多,但是讓我們為低版本適配也是一個苦逼的活兒。

       不過還好,在使用了 nineoldandroids 這個開源庫之後,總算是實現了這個效果。

       再給出兩張效果圖,分別是基於 TextView 和 ImageView 的點選效果:


圖1 TextView、ImageView應用後的點選效果示意圖

1.程式碼實現邏輯

       首先我們分析一下這種點選效果的實現邏輯。

       點選效果的處理主要分為兩個階段:

       a.手指按下:

              當用戶觸控到控制元件的時候,首先我們先讓控制元件顯示一層淺色遮罩,然後從手指按下位置開始,有一個深色遮罩逐漸擴大至整個控制元件。

       b.手指彈起:

              當用戶鬆開手指之後,這裡存在兩種情況,一種是深色遮罩已經擴大到了整個控制元件的範圍一種是深色遮罩尚未完全包圍整個控制元件

              對於前一種情況,我們簡單做一次透明度變化,讓遮罩逐漸消失即可;

              對於後一種情況,我們需要讓深色遮罩從當前的位置快速擴散到整個控制元件,同時也要做透明度變化,放置遮罩消失太過突兀。

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

       基本上整個程式碼的使用流程就到這裡了,感謝大家的閱覽,如果覺得對自己有幫助,還請頂一下。