Androidトップポップアップメッセージの3つの実装方法:WindowManager、PopupWindow、Toast
需要:ホームActivityの上部を上から下にスライドするとプロンプトが表示され、5秒後に自動的に下から上へスライドして消えます.
カスタムレイアウトファイル:layout_tips.xml
スライドアニメーションをカスタマイズするには
カスタムアニメーションかすたむあにめーしょん:anim_popup_show.xml
カスタム消去アニメーション:anim_popup_exit.xml
一、WindowManager実現
利点:現在のActivity内のすべてのFragment、Dialogの上に常に表示されます.欠点:Activityを切り替えると、新しいActivityで上書きされます.
二、PopupWindow実現
欠点:現在のActivityで新しく登場したFragment、Dialogで上書きされます.
三、Toast実現
利点:常に画面の最上位に表示され、新しいActivityで上書きされません.欠点:Android 7.0以降はアニメーションの表示/非表示をカスタマイズできません.デフォルトはグラデーションです.
カスタムレイアウトファイル: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;
}