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

首頁 > 系統 > Android > 正文

Android實現類似3D Touch菜單功能

2019-12-12 01:04:59
字體:
來源:轉載
供稿:網友

前言

在開發中,我們經常遇到需要菜單功能的實現,我們經常會參考其他人的優秀設計。比如3D Touch菜單,作為iphone6和iphone6s上引人注目的新功能。現在,我們希望盡力來模仿這種菜單設計,盡力,因為系統的差異,會導致很多東西實現起來有難度。

思路

想要盡力模仿這種菜單,經過分析,我覺得主要實現以下幾個點:

1)菜單的出現方式,在ios上,方式是用戶用手指用力按下,然而在Android上,受限于硬件,我們無法捕捉用力按壓這種動作,所以,我改用另一種比較次的方式,長按彈出,捕捉手指長按動作。

2)菜單的界面上,需要處理背景模糊效果。

3)菜單的觸摸事件處理,我們看到,手指長按之后,菜單出現,這時候手指不離開屏幕,滑動到菜單某個選項,再抬起,這時候這個選項會相應。

實現

背景模糊處理

經過一番調研,除了調用github上面大神的各種繪圖效果庫,我們想要自己實現大概有兩個思路。

RenderScript方案

RenderScript是由Android3.0引入,用來在Android上編寫高性能代碼的一種語言。優點:使用方便,Android官方API自帶,而且性能處理效果極好,缺點:需要API17以上。

使用非常簡單,我們只需要獲取RenderScript的實例,傳入模糊圖像需要的參數

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)  public Bitmap getRenderScriptBitmap(Context context, int radius, Bitmap bitmapOriginal) {    RenderScript rs = RenderScript.create(context);    final Allocation input = Allocation.createFromBitmap(rs, bitmapOriginal);    final Allocation output = Allocation.createTyped(rs, input.getType());    final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));    script.setRadius(radius);    script.setInput(input);    script.forEach(output);    output.copyTo(bitmapOriginal);    rs.destroy();    return bitmapOriginal;  } 

Java代碼層實現方案

通過java層代碼也可以實現圖像的模糊處理,github大神已經為我們實現了這種圖像算法

通過FastBlur算法實現圖片模糊,沒有版本兼容問題,但是如果我們需要模糊的圖像不小的時候,我們會發現模糊圖像需要的時間遠遠超過了我們能夠接受的范圍,如果加載大圖的話,那情況就更加糟糕了。一個比較好的處理方式是,在圖片進行模糊處理之前,先對圖像進行壓縮,在圖片模糊處理完畢之后,再按照原大小放大,這樣就能有效降低模糊處理的耗時。

這里我們做一個版本判斷

if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {  mIBlurry = BlurryFactory.createRenderScript();} else {  mIBlurry = BlurryFactory.createFastBlur();}

觸摸事件的處理

先來說說模糊層如何出現,肯定是要實現一個全屏效果,關于全屏效果,我們可以通過Dialog,懸浮窗,透明的Activity,或者在DectorView中插入覆蓋父布局的視圖,這四種方式都可以實現全屏效果,這里,我們選用在DectorView中插入視圖的方式來實現。

如何實現呢?

  /**   * 掛載到某個Activity的最頂層    * @param activity   */  private void attachActivity(Activity activity) {    ViewParent parent = getParent();    if(parent != null && parent instanceof ViewGroup) {      ViewGroup parentView = (ViewGroup) parent;      parentView.removeView(this);    }    FrameLayout decor = (FrameLayout)activity.getWindow().getDecorView();    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(        FrameLayout.LayoutParams.MATCH_PARENT,        FrameLayout.LayoutParams.MATCH_PARENT);    decor.addView(this, lp);  }

前面提到,手指長按,在菜單彈出之后,我們在手指不抬起的情況下,可以選擇菜單選項。這樣聽起來可能有些難以理解,我們都看過很多大神寫的View的觸摸事件解析,也有自己去研讀源碼,都對觸摸事件傳遞有一定的了解。

一般情況下,當我們長按界面里的某個View,之后在我們手指抬起之前,所有的觸摸事件都會交由這個View來處理,也就是targetView(當某個View消費了觸摸事件,那么它就會被設置為targetView,并且接收接下來傳遞的觸摸事件)。那么我們如何在手指不抬起的情況下,讓剛剛出現模糊層視圖來接管接下來的手指滑動,也就是ACTION_MOVE和ACTION_UP事件呢?

經常一番思考,我想到了一種比較委婉的方式…

我們都知道手指抬起的時候,DecorView以及其子視圖都會接收到一個ACTION_UP的觸摸事件,這個事件會告訴DecorView,這個手指觸摸系列動作已經結束,那么方法來了,我們并不需要手指真的抬起來,只需要模擬一個手指抬起的動作,也就是自己發送一個ACTION_UP事件,就可以讓DecorView接收到ACTION_UP事件,然后重新尋找targetView,也就是新出現的模糊層視圖,這時候我們再模擬發送一個ACTION_DOWN事件。

  /**   * 轉移觸摸事件   */  private void transferTouchEvent(final Activity activity) {    postDelayed(new Runnable() {      @Override      public void run() {        activity.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(),             SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0f, 0f, 0));        activity.getWindow().getDecorView().dispatchTouchEvent(MotionEvent.obtain(SystemClock            .uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0f, 0f, 0));      }    }, 200);  }

效果圖

最后的效果圖如下,由于時間比較少,有很多地方沒有好好完善,菜單的出現角度以及菜單的樣式不夠美觀,同時沒有判斷菜單出現在ICON上面還是下面。

這里寫圖片描述

github項目地址:點擊打開地址

效果思路仍不夠完善,待更好的方案。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 昌吉市| 洛川县| 绿春县| 怀宁县| 庄浪县| 临桂县| 方城县| 芒康县| 集贤县| 樟树市| 信宜市| 兴国县| 隆安县| 平远县| 那坡县| 白城市| 明星| 尉犁县| 西吉县| 九寨沟县| 茂名市| 类乌齐县| 烟台市| 綦江县| 成安县| 平顺县| 沭阳县| 永善县| 垫江县| 祁阳县| 保山市| 偃师市| 嘉兴市| 黄陵县| 道孚县| 娱乐| 抚远县| 邹平县| 高州市| 修水县| 湖南省|