You*_*ode 23 android android-studio
虽然Snackbar很漂亮,但在改变活动时它并不存在.Snackbar在完成活动之前我想确认使用a发送消息的情况下,这是一个无聊的事情.我已经考虑在退出活动之前暂停代码,但发现这是一个不好的做法.
如果我所描述的是不可能的,是否有任何类型的材料设计敬酒消息?或者制作矩形吐司消息的方法; 一个半径较小的圆边?
use*_*087 24
要创建具有跨多个活动可见的应用程序上下文的Snackbar:
WindowManageras系统服务FrameLayout(rootView用型)WindowManager.LayoutParams.TYPE_TOAST,并WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL于WindowManagerFrameLayout.onAttachedToWindow()调用onFrameLayoutFrameLayout(rootView)的窗口标记View.getWindowToken()ContextThemeWrapper使用应用程序上下文和派生创建一个@style/Theme.AppCompatFrameLayout(snackbarContainer)FrameLayout(snackbarContainer)类型WindowManager.LayoutParams.TYPE_APPLICATION_PANEL和标志WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODALView.onAttachedToWindow()调用onFrameLayoutFrameLayout(snackbarContainer)正常创建SnackbarView.onDismissed()回调到Snackbar并删除FrameLayouts(rootView和snackbarContainer)Snackbar.show()这里有一个工作包装器(注意:轻扫以解除不起作用.也许其他人找到正确的由CoordinatorLayout修复的WindowManager.LayoutParams标志来接收触摸事件):
public class SnackbarWrapper
{
private final CharSequence text;
private final int duration;
private final WindowManager windowManager;
private final Context appplicationContext;
@Nullable
private Snackbar.Callback externalCallback;
@Nullable
private Action action;
@NonNull
public static SnackbarWrapper make(@NonNull Context applicationContext, @NonNull CharSequence text, @Snackbar.Duration int duration)
{
return new SnackbarWrapper(applicationContext, text, duration);
}
private SnackbarWrapper(@NonNull final Context appplicationContext, @NonNull CharSequence text, @Snackbar.Duration int duration)
{
this.appplicationContext = appplicationContext;
this.windowManager = (WindowManager) appplicationContext.getSystemService(Context.WINDOW_SERVICE);
this.text = text;
this.duration = duration;
}
public void show()
{
WindowManager.LayoutParams layoutParams = createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_TOAST, null);
windowManager.addView(new FrameLayout(appplicationContext)
{
@Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
onRootViewAvailable(this);
}
}, layoutParams);
}
private void onRootViewAvailable(final FrameLayout rootView)
{
final CoordinatorLayout snackbarContainer = new CoordinatorLayout(new ContextThemeWrapper(appplicationContext, R.style.FOL_Theme_SnackbarWrapper))
{
@Override
public void onAttachedToWindow()
{
super.onAttachedToWindow();
onSnackbarContainerAttached(rootView, this);
}
};
windowManager.addView(snackbarContainer, createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, rootView.getWindowToken()));
}
private void onSnackbarContainerAttached(final View rootView, final CoordinatorLayout snackbarContainer)
{
Snackbar snackbar = Snackbar.make(snackbarContainer, text, duration);
snackbar.setCallback(new Snackbar.Callback()
{
@Override
public void onDismissed(Snackbar snackbar, int event)
{
super.onDismissed(snackbar, event);
// Clean up (NOTE! This callback can be called multiple times)
if (snackbarContainer.getParent() != null && rootView.getParent() != null)
{
windowManager.removeView(snackbarContainer);
windowManager.removeView(rootView);
}
if (externalCallback != null)
{
externalCallback.onDismissed(snackbar, event);
}
}
@Override
public void onShown(Snackbar snackbar)
{
super.onShown(snackbar);
if (externalCallback != null)
{
externalCallback.onShown(snackbar);
}
}
});
if (action != null)
{
snackbar.setAction(action.text, action.listener);
}
snackbar.show();
}
private WindowManager.LayoutParams createDefaultLayoutParams(int type, @Nullable IBinder windowToken)
{
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.format = PixelFormat.TRANSLUCENT;
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.gravity = GravityCompat.getAbsoluteGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, ViewCompat.LAYOUT_DIRECTION_LTR);
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
layoutParams.type = type;
layoutParams.token = windowToken;
return layoutParams;
}
@NonNull
public SnackbarWrapper setCallback(@Nullable Snackbar.Callback callback)
{
this.externalCallback = callback;
return this;
}
@NonNull
public SnackbarWrapper setAction(CharSequence text, final View.OnClickListener listener)
{
action = new Action(text, listener);
return this;
}
private static class Action
{
private final CharSequence text;
private final View.OnClickListener listener;
public Action(CharSequence text, View.OnClickListener listener)
{
this.text = text;
this.listener = listener;
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
一旦SnackbarWrapper定义,您可以像这样使用它:
final SnackbarWrapper snackbarWrapper = SnackbarWrapper.make(getApplicationContext(),
"Test snackbarWrapper", Snackbar.LENGTH_LONG);
snackbarWrapper.setAction(R.string.snackbar_text,
new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "Action",
Toast.LENGTH_SHORT).show();
}
});
snackbarWrapper.show();
Run Code Online (Sandbox Code Playgroud)
如果您没有主题,可以快速定义一个styles.xml:
<style name="FOL_Theme_SnackbarWrapper" parent="@style/Theme.AppCompat">
<!--Insert customization here-->
</style>
Run Code Online (Sandbox Code Playgroud)
编辑
对于那些在Android Oreo上获得Bad Token Exception的人,请将TYPE_TOAST更改为TYPE_APPLICATION_OVERLAY.这是因为Android Oreo实现了绘制应用程序的特殊权限.您可以使用以下方式请求此权限:
if(!Settings.canDrawOverlays(Activity.this){
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, URI.parse("package:" + getPackageName()));
startActivityForResult(intent, REQ_CODE);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10997 次 |
| 最近记录: |