Android實(shí)現(xiàn)類似3D Touch菜單功能
前言
在開發(fā)中,我們經(jīng)常遇到需要菜單功能的實(shí)現(xiàn),我們經(jīng)常會參考其他人的優(yōu)秀設(shè)計(jì)。比如3D Touch菜單,作為iphone6和iphone6s上引人注目的新功能?,F(xiàn)在,我們希望盡力來模仿這種菜單設(shè)計(jì),盡力,因?yàn)橄到y(tǒng)的差異,會導(dǎo)致很多東西實(shí)現(xiàn)起來有難度。
思路
想要盡力模仿這種菜單,經(jīng)過分析,我覺得主要實(shí)現(xiàn)以下幾個點(diǎn):
1)菜單的出現(xiàn)方式,在ios上,方式是用戶用手指用力按下,然而在Android上,受限于硬件,我們無法捕捉用力按壓這種動作,所以,我改用另一種比較次的方式,長按彈出,捕捉手指長按動作。
2)菜單的界面上,需要處理背景模糊效果。
3)菜單的觸摸事件處理,我們看到,手指長按之后,菜單出現(xiàn),這時候手指不離開屏幕,滑動到菜單某個選項(xiàng),再抬起,這時候這個選項(xiàng)會相應(yīng)。
實(shí)現(xiàn)
背景模糊處理
經(jīng)過一番調(diào)研,除了調(diào)用github上面大神的各種繪圖效果庫,我們想要自己實(shí)現(xiàn)大概有兩個思路。
RenderScript方案
RenderScript是由Android3.0引入,用來在Android上編寫高性能代碼的一種語言。優(yōu)點(diǎn):使用方便,Android官方API自帶,而且性能處理效果極好,缺點(diǎn):需要API17以上。
使用非常簡單,我們只需要獲取RenderScript的實(shí)例,傳入模糊圖像需要的參數(shù)
@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代碼層實(shí)現(xiàn)方案
通過java層代碼也可以實(shí)現(xiàn)圖像的模糊處理,github大神已經(jīng)為我們實(shí)現(xiàn)了這種圖像算法。
通過FastBlur算法實(shí)現(xiàn)圖片模糊,沒有版本兼容問題,但是如果我們需要模糊的圖像不小的時候,我們會發(fā)現(xiàn)模糊圖像需要的時間遠(yuǎn)遠(yuǎn)超過了我們能夠接受的范圍,如果加載大圖的話,那情況就更加糟糕了。一個比較好的處理方式是,在圖片進(jìn)行模糊處理之前,先對圖像進(jìn)行壓縮,在圖片模糊處理完畢之后,再按照原大小放大,這樣就能有效降低模糊處理的耗時。
這里我們做一個版本判斷
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
mIBlurry = BlurryFactory.createRenderScript();
} else {
mIBlurry = BlurryFactory.createFastBlur();
}
觸摸事件的處理
先來說說模糊層如何出現(xiàn),肯定是要實(shí)現(xiàn)一個全屏效果,關(guān)于全屏效果,我們可以通過Dialog,懸浮窗,透明的Activity,或者在DectorView中插入覆蓋父布局的視圖,這四種方式都可以實(shí)現(xiàn)全屏效果,這里,我們選用在DectorView中插入視圖的方式來實(shí)現(xiàn)。
如何實(shí)現(xiàn)呢?
/**
* 掛載到某個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);
}
前面提到,手指長按,在菜單彈出之后,我們在手指不抬起的情況下,可以選擇菜單選項(xiàng)。這樣聽起來可能有些難以理解,我們都看過很多大神寫的View的觸摸事件解析,也有自己去研讀源碼,都對觸摸事件傳遞有一定的了解。
一般情況下,當(dāng)我們長按界面里的某個View,之后在我們手指抬起之前,所有的觸摸事件都會交由這個View來處理,也就是targetView(當(dāng)某個View消費(fèi)了觸摸事件,那么它就會被設(shè)置為targetView,并且接收接下來傳遞的觸摸事件)。那么我們?nèi)绾卧谑种覆惶鸬那闆r下,讓剛剛出現(xiàn)模糊層視圖來接管接下來的手指滑動,也就是ACTION_MOVE和ACTION_UP事件呢?
經(jīng)常一番思考,我想到了一種比較委婉的方式…
我們都知道手指抬起的時候,DecorView以及其子視圖都會接收到一個ACTION_UP的觸摸事件,這個事件會告訴DecorView,這個手指觸摸系列動作已經(jīng)結(jié)束,那么方法來了,我們并不需要手指真的抬起來,只需要模擬一個手指抬起的動作,也就是自己發(fā)送一個ACTION_UP事件,就可以讓DecorView接收到ACTION_UP事件,然后重新尋找targetView,也就是新出現(xiàn)的模糊層視圖,這時候我們再模擬發(fā)送一個ACTION_DOWN事件。
/**
* 轉(zhuǎn)移觸摸事件
*/
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);
}
效果圖
最后的效果圖如下,由于時間比較少,有很多地方?jīng)]有好好完善,菜單的出現(xiàn)角度以及菜單的樣式不夠美觀,同時沒有判斷菜單出現(xiàn)在ICON上面還是下面。

github項(xiàng)目地址:點(diǎn)擊打開地址。
效果思路仍不夠完善,待更好的方案。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 安卓(Android)實(shí)現(xiàn)3DTouch效果
- Android左右滑出菜單實(shí)例分析
- android底部菜單欄實(shí)現(xiàn)原理與代碼
- android popwindow實(shí)現(xiàn)左側(cè)彈出菜單層及PopupWindow主要方法介紹
- 基于Android實(shí)現(xiàn)點(diǎn)擊某個按鈕讓菜單選項(xiàng)從按鈕周圍指定位置彈出
- Android ListView長按彈出菜單二種實(shí)現(xiàn)方式示例
- Android界面設(shè)計(jì)(APP設(shè)計(jì)趨勢 左側(cè)隱藏菜單右邊顯示content)
- Android開發(fā)技巧之我的菜單我做主(自定義菜單)
- Android仿QQ空間底部菜單示例代碼
- Android實(shí)現(xiàn)原生側(cè)滑菜單的超簡單方式
相關(guān)文章
詳解Android中OkHttp3的例子和在子線程更新UI線程的方法
本篇文章主要介紹了詳解Android中OkHttp3的例子和在子線程更新UI線程的方法 ,非常具有實(shí)用價值,需要的朋友可以參考下2017-05-05
RecyclerView焦點(diǎn)跳轉(zhuǎn)BUG優(yōu)化的方法
這篇文章主要介紹了RecyclerView焦點(diǎn)跳轉(zhuǎn)BUG優(yōu)化的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04
Android adb logcat 命令查看日志詳細(xì)介紹
這篇文章主要介紹了Android adb logcat 命令詳細(xì)介紹的相關(guān)資料,這里對logcat 命令進(jìn)行了詳細(xì)介紹,并介紹了過濾日志輸出的知識,需要的朋友可以參考下2016-12-12
android實(shí)現(xiàn)播放網(wǎng)絡(luò)視頻
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)播放網(wǎng)絡(luò)視頻,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-04-04
Android應(yīng)用實(shí)踐之?dāng)?shù)獨(dú)游戲開發(fā)
這篇文章主要為大家詳細(xì)介紹了Android應(yīng)用實(shí)踐之?dāng)?shù)獨(dú)游戲開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
學(xué)習(xí)使用Material Design控件(三)使用CardView實(shí)現(xiàn)卡片效果
這篇文章主要為大家介紹了學(xué)習(xí)使用Material Design控件的詳細(xì)教程,如何使用CardView實(shí)現(xiàn)卡片效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
詳解Android App中的AsyncTask異步任務(wù)執(zhí)行方式
這篇文章主要介紹了Android App中的AsyncTask異步任務(wù)執(zhí)行方式,文中舉了一個打開網(wǎng)絡(luò)圖片的例子幫助大家直觀理解,需要的朋友可以參考下2016-04-04

