6

谷歌收件箱是如何顯示一個快餐欄覆蓋鍵盤?

Google Inbox如何在鍵盤上顯示快餐欄(覆蓋,分層)?這不是默認行爲,我已經使用基本協調器佈局,鍵盤打開和小吃棒進行了測試:默認行爲是在後面顯示小鍵盤鍵盤。對於這個問題,SO上有很多答案:'我如何在以上的快捷鍵上顯示鍵盤',但我還沒有找到如何重現Google自己的Inbox應用程序快餐欄行爲。

你能告訴我如何做到這一點嗎?

+0

我嘗試將快餐欄的視圖的高度(默認爲6)設置爲大數字,但這不起作用。我嘗試了高達5000的高程! – Erik

+1

我假設他們必須使用覆蓋窗口(例如,8.0+以前的'TYPE_SYSTEM_OVERLAY','8.0的TYPE_APPLICATION_OVERLAY')。我不使用Google收件箱,因此我無法測試這種情況。但是,如果Inbox在8.0+上沒有這種行爲,但是在7.1和更舊的版本上,那麼它很可能是覆蓋圖,因爲[覆蓋圖不能覆蓋8.0+上的IME](https://developer.android.com /about/versions/oreo/android-8.0-changes.html#cwt)。 – CommonsWare

+0

'高程'隻影響你的應用程序佈局。我認爲創建具有不同上下文的Snakebar可能會有一些技巧。 – sakiM

回答

5

收件箱不使用標準Snackbar,也不使用疊加窗口,它使用自定義視圖。我反編譯APK以驗證它們如何實現這種效果,並試圖重現一個最小的例子。

,首先創建一個新的佈局custom_snackbar.xml

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:background="#323232" 
    android:paddingLeft="10dp" 
    android:paddingRight="10dp"> 

    <TextView 
     android:id="@+id/text" 
     android:layout_width="0dp" 
     android:layout_height="match_parent" 
     android:layout_weight="1" 
     android:gravity="center_vertical" 
     android:text="Marked done" 
     android:textColor="@android:color/white"/> 

    <Button 
     android:id="@+id/button" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:background="@android:color/transparent" 
     android:gravity="center_vertical" 
     android:minWidth="48dp" 
     android:text="undo" 
     android:textAllCaps="true" 
     android:textColor="#a1c2fa"/> 

</LinearLayout> 

然後創建這些方法來顯示並關閉自定義小吃吧:

private View customSnackbar; 

private void showCustomSnackbar(final Context context) { 
    customSnackbar = LayoutInflater.from(context).inflate(R.layout.custom_snackbar, null, false); 
    customSnackbar.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      //action implementation 
     } 
    }); 

    WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); 
    lp.height = WindowManager.LayoutParams.WRAP_CONTENT; 
    lp.width = WindowManager.LayoutParams.MATCH_PARENT; 
    lp.format = PixelFormat.TRANSLUCENT; 
    lp.gravity = Gravity.BOTTOM; 
    lp.flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | 
      WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 
      WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 
    customSnackbar.setLayoutParams(lp); 

    WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE); 

    if (windowManager != null) { 
     windowManager.addView(customSnackbar, customSnackbar.getLayoutParams()); 

     Point m = new Point(); 
     windowManager.getDefaultDisplay().getSize(m); 
     int childMeasureSpecWidth = ViewGroup.getChildMeasureSpec(View.MeasureSpec.makeMeasureSpec(m.x, View.MeasureSpec.EXACTLY), 0, lp.width); 
     int childMeasureSpecHeight = ViewGroup.getChildMeasureSpec(View.MeasureSpec.makeMeasureSpec(m.y, View.MeasureSpec.EXACTLY), 0, lp.height); 
     customSnackbar.measure(childMeasureSpecWidth, childMeasureSpecHeight); 

     customSnackbar.setTranslationY(customSnackbar.getMeasuredHeight()); 
     customSnackbar.animate() 
       .setDuration(300) 
       .translationX(0.0f) 
       .translationY(0.0f); 
    } 
} 

private void dismissCustomSnackbar(final Context context) { 
    customSnackbar.animate() 
      .setDuration(300) 
      .translationX(0.0f) 
      .translationY(customSnackbar.getMeasuredHeight()) 
      .withEndAction(new Runnable() { 
       @Override 
       public void run() { 
        WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE); 
        if (windowManager != null) { 
         windowManager.removeView(customSnackbar); 
        } 
       } 
      }); 
} 

這是得到的結果:

Screenshot

+1

我不會'WindowManager'太多......但爲什麼這能夠出現在IME上?我認爲Android 8.0中有關'WindowManager'添加窗口的更改應該可以防止這種情況發生。無論如何,好的工作! – CommonsWare

+0

Android 8.0的限制似乎只適用於'TYPE_APPLICATION_OVERLAY'類型。在這個例子中,視圖具有缺省類型'TYPE_APPLICATION'。 –

+0

謝謝,這真棒。我會稍後在我的應用程序中嘗試此操作,並在發生任何怪癖或邊緣情況時向我們報告。我也猜想有可能以常規的方式建立一個'Snackbar',然後,如果鍵盤是打開的,而不是定期顯示它,使用這種方法將它顯示在鍵盤前面。這種自定義小吃棒行爲可以適應不同的鍵盤情況。 – Erik