Android頂部彈出提示語的三種實現方式:WindowManager、PopupWindow、Toast

需求:在主頁Activity頂部從上向下滑動出現提示條,且5秒後自動從下向上滑動消失。

自定義佈局文件:layout_tips.xml

// layout_tips.xml
<LinearLayout
      android:layout_width="match_parent"
      android:layout_height="120px"
      android:paddingStart="20px"
      android:paddingEnd="20px"
      android:gravity="center"
      android:background="#cc000000">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30px"
        android:layout_marginBottom="30px"
        android:text="提示語"
        android:textSize="38px"
        android:textColor="@android:color/white"/>
</LinearLayout>

自定義滑動動畫:

<style name="popwindowAnimStyle" parent="android:Animation">
    <item name="android:windowEnterAnimation">@anim/anim_popup_show</item>
    <item name="android:windowExitAnimation">@anim/anim_popup_exit</item>
</style>

自定義出現動畫:anim_popup_show.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate
    android:fromYDelta="-120%"
    android:toYDelta="0"
    android:duration="400"/>
</set>

自定義消失動畫:anim_popup_exit.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
  <translate
      android:fromYDelta="0"
      android:toYDelta="-120%"
      android:duration="400"/>
</set>

一、WindowManager實現

優點:可始終顯示在當前Activity內所有Fragment、Dialog之上;
缺點:若切換Activity,則被新Activity覆蓋。

View contentView = LayoutInflater.from(this).inflate(R.layout.layout_tips, null);
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
if(windowManager != null) {
  WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
  layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |	//不攔截頁面點擊事件
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
  layoutParams.format = PixelFormat.TRANSLUCENT;
  layoutParams.gravity = Gravity.TOP;
  layoutParams.y = (int) getResources().getDimension(R.dimen.y30);
  layoutParams.height = (int) getResources().getDimension(R.dimen.y119);
  layoutParams.windowAnimations = R.style.popwindowAnimStyle;	//自定義動畫
  windowManager.addView(contentView, layoutParams);

  new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        if(windowManager != null) {
	        windowManager.removeViewImmediate(contentView);
	        windowManager = null;
      	}
      }
    }, 3000);
}

二、PopupWindow實現

缺點:會被當前Activity新出現的Fragment、Dialog覆蓋。

View contentView = LayoutInflater.from(this).inflate(R.layout.layout_tips, null);
contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
DisplayMetrics dm = getResources().getDisplayMetrics();
PopupWindow popupWindow = new PopupWindow(contentView, dm.widthPixels - contentView.getPaddingStart() * 2,
    (int) getResources().getDimension(R.dimen.y120));
popupWindow.setOutsideTouchable(false);	//點擊外部區域不消失
popupWindow.setTouchable(false);
popupWindow.setBackgroundDrawable(null);
popupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
popupWindow.setAnimationStyle(R.style.popwindowAnimStyle);	//自定義動畫
popupWindow.showAtLocation(tvShopDeviceName, Gravity.TOP | Gravity.CENTER_HORIZONTAL,
    0, (int) getResources().getDimension(R.dimen.y30));	//指定頂部位置

new Handler().postDelayed(new Runnable() {
  @Override
  public void run() {
    popupWindow.dismiss();
  }
}, 3000);

三、Toast實現

優點:可始終顯示在屏幕最上層,不被新Activity覆蓋;
缺點:Android 7.0後無法自定義顯示/隱藏動畫,默認爲漸隱漸現。

View contentView = LayoutInflater.from(this).inflate(R.layout.layout_tips, null);
Toast videoToast = Toast.makeText(this, "", Toast.LENGTH_LONG);
videoToast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, (int) getResources().getDimension(R.dimen.y30));
videoToast.setView(contentView);
try {
  Object mTN = getField(videoToast, "mTN");
  if(mTN != null) {
    Object mParams = getField(mTN, "mParams");
    if(mParams instanceof WindowManager.LayoutParams) {
      WindowManager.LayoutParams params = (WindowManager.LayoutParams) mParams;
      //params.windowAnimations = R.style.popwindowAnimStyle;	//自定義動畫無效
      params.width = dm.widthPixels - contentView.getPaddingStart() * 2;
      params.height = (int) getResources().getDimension(R.dimen.y120);
    }
  }
} catch (Exception e){
  e.printStackTrace();
}
videoToast.show();

private Object getField(Object object, String fieldName)
    throws NoSuchFieldException, IllegalAccessException{
 Field field = object.getClass().getDeclaredField(fieldName);
 if(field != null) {
   field.setAccessible(true);
   return field.get(object);
 }
 return null;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章