6

Google Inboxはキーボードを覆うスナックバーをどのように表示しますか?

Google Inboxではどのようにキーボードの上にスナックバーが表示されますか?これはデフォルトの動作ではありません。これは基本的なコーディネーターレイアウト、キーボードが開いている状態、およびスナークバーでテストされています。デフォルトの動作ではキーボードのの後ろにsnackbar が表示されます。 「スヌーカーバーをキーボードの上にと表示するにはどうすればいいですか?ですが、Google独自の受信トレイアプリのスナックバーの動作を再現する方法は見つかりませんでした。

これを達成する方法を教えてもらえますか?

+0

デフォルトでは6であるsnackbarのビューの標高を大きな数値に設定しようとしましたが、これは役に立ちません。私は5000まで高度を試しました! – Erik

+1

私はオーバーレイウィンドウ(例えば、8.0より前の 'TYPE_SYSTEM_OVERLAY'、8.0+では' TYPE_APPLICATION_OVERLAY'など)を使用しなければならないと仮定します。私はこのシナリオをテストすることができないので私はGoogleの受信トレイを使用しません。しかし、Inboxが8.0以上でこの動作をしなくても、7.1以降では、[オーバーレイはIMEを8.0+にオーバーレイできないため]オーバーレイになる可能性が非常に高くなります(https://developer.android.com /about/versions/oreo/android-8.0-changes.html#cwt)。 – CommonsWare

+0

'elevations'はアプリケーションレイアウト内でのみ影響を与えます。私は、異なるコンテキストでスネークバーを作成するといくつかのトリックがあるかもしれないと思う。 – sakiM

答えて

5

受信トレイは標準Snackbarを使用せず、オーバーレイウィンドウも使用しません。カスタムビューを使用します。私はAPKを逆コンパイルして、どのようにこの効果を達成したかを検証し、最小限の例を再現しようとしました。その後、カスタムスナックバーを表示し、却下するこれらのメソッドを作成

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

これは結果を得ている

まず第一には、新しいレイアウトcustom_snackbar.xmlを作成します

Screenshot

+1

私は 'WindowManager'を大いに混乱させることはありませんが、なぜこれはIME上に現れるのですか?私は、Android 8.0の「WindowManager」追加ウィンドウに関する変更が、このようなことを防ぐためのものだと考えました。関係なく、素敵な仕事! – CommonsWare

+0

Android 8.0の制限はTYPE_APPLICATION_OVERLAYタイプにのみ適用されるようです。この例では、ビューはデフォルトの型 'TYPE_APPLICATION'を持っています。 –

+0

ありがとう、それは素晴らしいです。私は後でこれを私のアプリで試してみましょう。そして、奇妙な事件や縁起がある場合は、ここで報告します。私はまた、通常の方法で 'Snackbar'を構築し、キーボードが開いていれば定期的に表示するのではなく、このメソッドを使ってキーボードの前に表示することが可能であると思います。このようにして、このカスタムスナックバーの動作をさまざまなキーボードの状況に合わせることができます。 – Erik

関連する問題