Toast的使用
**Toast的使用大家都不陌生,通常情况下,我们不会在Toast上进行过于复杂的操作,只是通知用户一些消息。 今天我使用Toast来进行需要的悬浮窗改造,同时,添加用户点击事件的响应。**
首先预览一下整体效果:
两种悬浮窗都有响应点击事件 ,点击”X”后悬浮窗会消失。
话不多说,代码走起~~
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingRight="15dp">
<RelativeLayout
android:id="@+id/emui_window_big_info"
android:layout_width="324dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#fff"
android:visibility="visible">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/linearLayout">
<RelativeLayout
android:layout_width="324dp"
android:background="#008cff"
android:layout_height="wrap_content">
<TextView
android:id="@+id/guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:paddingTop="21dp"
android:paddingLeft="11dp"
android:textSize="15sp"
android:text="悬浮窗标题1"/>
<TextView
android:id="@+id/guide2"
android:layout_below="@id/guide"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:paddingLeft="12dp"
android:paddingBottom="17dp"
android:textSize="15sp"
android:text="悬浮窗标题2"/>
<LinearLayout
android:id="@+id/emui_window_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp"
android:layout_alignParentRight="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/close"/>
</LinearLayout>
</RelativeLayout>
<View
android:layout_width="307dp"
android:layout_height="1dp"
android:layout_marginRight="9dp"
android:layout_marginLeft="9dp"
android:background="#e5e5e5"/>
<RelativeLayout
android:layout_width="324dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="43dp"
android:textColor="#333333"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:textSize="14sp"
android:text="文字1"/>
</RelativeLayout>
<View
android:layout_width="307dp"
android:layout_height="1dp"
android:layout_marginRight="9dp"
android:layout_marginLeft="9dp"
android:background="#e5e5e5"/>
<RelativeLayout
android:layout_width="324dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="43dp"
android:textColor="#333333"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:textSize="14sp"
android:text="文字2"/>
</RelativeLayout>
<View
android:layout_width="307dp"
android:layout_height="1dp"
android:layout_marginRight="9dp"
android:layout_marginLeft="9dp"
android:background="#e5e5e5"/>
<RelativeLayout
android:layout_width="324dp"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="43dp"
android:textColor="#333333"
android:gravity="center_vertical"
android:paddingLeft="12dp"
android:textSize="14sp"
android:text="文字3"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
</FrameLayout>
1.使用系统地Toast去完成悬浮窗时,使用WindowManager并指定当前悬浮窗的类型为TYPE_TOAST,同时根据需要指定gravity,flags,type.
show()的时候,调用 mWindowManager.addView(mView, mLayoutParams)即可。
remove()的时候,调用 mWindowManager.removeView(mView);即可。
package com.example.sunqi.mytoast;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
/**
* Created by sunqi on 2017/3/10.
*/
public class SystemToastWindow implements View.OnClickListener{
protected WindowManager mWindowManager;
protected WindowManager.LayoutParams mLayoutParams;
protected Context mContext;
protected View mView;
protected boolean mIsShow =
false;
private int mCurWindowType = WindowManager.LayoutParams.TYPE_TOAST;
private void initView() {
View rootView = LayoutInflater.from(mContext).inflate(R.layout.system_float_window_layout,
null);
mView = rootView;
((TextView)mView.findViewById(R.id.guide)).setText(
"系统Toast悬浮窗");
mView.findViewById(R.id.emui_window_close).setOnClickListener(
this);
}
public SystemToastWindow(Context context) {
mContext = context;
}
private void init(Context context) {
mLayoutParams =
new WindowManager.LayoutParams();
mLayoutParams.format = PixelFormat.RGBA_8888;
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mLayoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
mLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mLayoutParams.type = mCurWindowType;
initView();
}
public void remove() {
if (mWindowManager !=
null) {
try {
if (
null != mView) {
mWindowManager.removeView(mView);
mView =
null;
}
mIsShow =
false;
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public void show() {
init(mContext);
if (
null != mWindowManager &&
null != mView) {
try {
mWindowManager.addView(mView, mLayoutParams);
mIsShow =
true;
}
catch (WindowManager.BadTokenException e) {
}
catch (Exception e) {
}
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.emui_window_close:
remove();
break;
}
}
public boolean isShow() {
return mIsShow;
}
}
2.使用反射的Toast去完成悬浮窗时,自定义一个FloatToastManager,同时根据需要指定gravity,flags,type.自定义FloatToastWindow
package com.example.sunqi.mytoast;
import android.content.Context;
import android.graphics.PixelFormat;
import android.icu.text.DateFormat;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
/**
* 反射Toast控制显示的位置,时间,动画,View
* Created by sunqi on 2017/2/27.
*/
public class FloatToastManager {
private Context mContext;
private Field mParamsField;
private WindowManager.LayoutParams mParams;
private Toast mToast;
private Object mTN;
private Method mShowMethod;
private Method mHideMethod;
private boolean isShow =
false;
private int mGravity = Gravity.CENTER;
private int mXOffset =
0;
private int mYOffset =
0;
private int mHeight = WindowManager.LayoutParams.MATCH_PARENT;
private int mWidth = WindowManager.LayoutParams.MATCH_PARENT;
private boolean misInited =
false;
private View mView;
public FloatToastManager(Context context){
mContext = context;
mToast =
new Toast(mContext);
}
public void setGravity(
int gravity,
int xOffset,
int yOffset){
mGravity = gravity;
mXOffset = xOffset;
mYOffset = yOffset;
}
public void setSize(
int height,
int width){
mHeight = height;
mWidth = width;
}
private void initVar(){
if (misInited){
return;
}
try {
Field tnField =mToast.getClass().getDeclaredField(
"mTN");
tnField.setAccessible(
true);
mToast.setGravity(mGravity,mXOffset,mYOffset);
mTN = tnField.get(mToast);
mShowMethod = mTN.getClass().getMethod(
"show");
mHideMethod = mTN.getClass().getMethod(
"hide");
mParamsField = mTN.getClass().getDeclaredField(
"mParams");
mParamsField.setAccessible(
true);
mParams = (WindowManager.LayoutParams) mParamsField.get(mTN);
mParams.height = mHeight;
mParams.width = mWidth;
mParams.format = PixelFormat.RGBA_8888;
mParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
}
catch (Exception e) {
e.printStackTrace();
}
}
public void showViewOther(View view){
initVar();
if (isShow)
return;
mToast.setView(view);
try {
/**调用tn.mShowMethod()之前一定要先设置mNextView*/
Field tnNextViewField = mTN.getClass().getDeclaredField(
"mNextView");
tnNextViewField.setAccessible(
true);
tnNextViewField.set(mTN,mToast.getView());
mShowMethod.invoke(mTN);
isShow =
true;
mView = view;
}
catch (Exception e){
e.printStackTrace();
}
}
public void hideView() {
if (!isShow)
return;
try {
if (
null != mView) {
mView.setVisibility(View.INVISIBLE);
mView.postDelayed(
new Runnable() {
@Override
public void run() {
if (
null != mView) {
mView.setVisibility(View.VISIBLE);
mView =
null;
}
}
},
100);
}
mHideMethod.invoke(mTN);
isShow =
false;
Log.i(
"FloatToastManager",
"hideView called");
}
catch (Exception e) {
e.printStackTrace();
Log.i(
"FloatToastManager",
"hideView exception " + e.getMessage());
}
}
}
package com.example.sunqi.mytoast;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
/**
* Created by sunqi on 2017/3/10.
*/
public class FloatToastWindow implements View.OnClickListener{
protected FloatToastManager mfloatToastManager;
protected Context mContext;
protected View mView;
protected boolean mIsShow =
false;
private void initView() {
View rootView = LayoutInflater.from(mContext).inflate(R.layout.system_float_window_layout,
null);
mView = rootView;
((TextView)mView.findViewById(R.id.guide)).setText(
"反射使用Toast悬浮窗");
mView.findViewById(R.id.emui_window_close).setOnClickListener(
this);
}
public FloatToastWindow(Context context) {
mContext = context;
}
private void init(Context context) {
mfloatToastManager =
new FloatToastManager(mContext);
initView();
}
public void remove() {
if (mfloatToastManager !=
null) {
try {
if (
null != mView) {
mfloatToastManager.hideView();
mView =
null;
}
mIsShow =
false;
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public void show() {
init(mContext);
if (
null != mfloatToastManager &&
null != mView) {
try {
mfloatToastManager.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL ,
0 ,
0 );
mfloatToastManager.setSize(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT);
mfloatToastManager.showViewOther(mView);
mIsShow =
true;
}
catch (Exception e) {
}
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.emui_window_close:
remove();
break;
}
}
public boolean isShow() {
return mIsShow;
}
}
3.具体地Window调用:
package com.example.sunqi.mytoast;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
private SystemToastWindow systemToastWindow;
private FloatToastWindow floatToastWindow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
systemToastWindow =
new SystemToastWindow(
this);
systemToastWindow.show();
floatToastWindow =
new FloatToastWindow(
this);
floatToastWindow.show();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onBackPressed() {
super.onBackPressed();
if (systemToastWindow !=
null && systemToastWindow.isShow()){
systemToastWindow.remove();
}
if (floatToastWindow !=
null && floatToastWindow.isShow()){
floatToastWindow.remove();
}
}
}
详细代码可以参考我的具体代码项目:MyToast代码