a brief introduction
1.1 The pop-up box refers to the window floating on the page, such as keyboard pop-up box, toast pop-up box, confirmation pop-up box, drop-down selection box, application floating box, etc.
1.2 There are also many bullet box controls, such as the commonly used Spinner, Dialog, Toast, PopWindow, etc., as well as the newly added SnackBar, DialogFragment, etc.
Two Spinner drop-down selection to use
2.1 Spinner root Listview, Gridview, etc. are products of the same era, so the usage is similar to them, mainly using BaseAdapter to load data sources
2.2 Use the Adapter provided by the system , which is easy to use, but the style is fixed, the data model is fixed, and it can only be of String type.
renderings
Layout file, add Spinner control
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:background="#eeeeee">
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
The java file sets the data source and configuration
private void initSystemAdapter(){
//设置数据源
List<String> list = new ArrayList<String>();
list.add("苹果");
list.add("香蕉");
list.add("橘子");
list.add("香蕉");
//设置系统适配器
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
//设置弹出偏移位置
spinner.setDropDownVerticalOffset(40);
//点击监听
spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(SpinnerActivity.this, list.get(position), Toast.LENGTH_SHORT).show();
}
});
}
Note: The system Adapter style is fixed, there are the following types
simple_spinner_dropdown_item (list-higher spacing is better)
simple_spinner_item (list-tight spacing is not good-looking)
simple_list_item_checked (check box-selected with green groove)
simple_list_item_single_choice (radio button)
2.3 Custom adapter , high flexibility, can set any type of data source and style
renderings
Custom item layout item_fruit_list.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_name"
android:layout_width="100dp"
android:layout_height="30dp"
android:background="#00ffff"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text="条目"
android:textSize="15sp" />
</LinearLayout>
Custom data source FruitBean.java
public class FruitBean {
public String name;
public FruitBean(String name) {
this.name = name;
}
}
Custom adapter CustomerAdapter.java
public class CustomerAdapter extends BaseAdapter {
private Context mContext;
private List<FruitBean> mList;
public CustomerAdapter(Context mContext, List<FruitBean> mList) {
this.mContext = mContext;
this.mList = mList;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_fruit_list, null);
holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvName.setText(mList.get(position).name);
return convertView;
}
class ViewHolder {
public TextView tvName;
}
}
spinner configuration custom adapter
private void initCustomerAdapter(){
//设置数据源
List<FruitBean> list = new ArrayList<>();
list.add(new FruitBean("苹果"));
list.add(new FruitBean("香蕉"));
list.add(new FruitBean("橘子"));
list.add(new FruitBean("香蕉"));
//设置系统适配器
CustomerAdapter customerAdapter=new CustomerAdapter(this,list);
spinner.setAdapter(customerAdapter);
//设置弹出偏移位置
spinner.setDropDownVerticalOffset(40);
}
The use of three Dialog
3.1 Dialog is the most frequently used bullet box besides Toast. Various loading boxes, prompt boxes, and selection boxes are also mostly used in Dialog
3.2 Dialog supports any layout and pop-up position, so it is very flexible.
3.2 Example renderings
3.3 Create a custom Dialog
dialog_confirm.xm
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_bg_fffff_corner10"
android:orientation="vertical"
android:paddingLeft="25dp"
android:paddingTop="20dp"
android:paddingRight="25dp"
android:paddingBottom="@dimen/dimen_20">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="退出提示"
android:textColor="@color/color_333333"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="是否对本地编辑的内容进行保存?"
android:textColor="@color/color_333333"
android:textSize="@dimen/text_14" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dimen_20"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:background="@drawable/shape_bg_1677ff_corners7_border"
android:gravity="center"
android:paddingTop="@dimen/dimen_9"
android:paddingBottom="@dimen/dimen_9"
android:text="取消"
android:textColor="@color/color_1677ff"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:background="@drawable/shape_bg_1677ff_corners7"
android:gravity="center"
android:paddingTop="@dimen/dimen_9"
android:paddingBottom="@dimen/dimen_9"
android:text="立即充值"
android:textColor="@color/white"
android:textSize="@dimen/sp_14" />
</LinearLayout>
</LinearLayout>
Set the dialog style custom_dialog.style, translucency, title, background, popup animation, etc.
<style name="custom_dialog" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<!-- Dialog的windowFrame框为无 -->
<item name="android:windowIsFloating">true</item>
<!-- 是否漂现在activity上 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 是否半透明 -->
<item name="android:windowNoTitle">true</item>
<item name="android:background">@null</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<!-- 去除黑色边框的关键设置项 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 屏幕背景是否变暗 -->
<item name="android:backgroundDimAmount">0.7</item>
</style>
Need to inherit the system Dialog parent class
public class ConfirmDialog extends Dialog {
private Context context;
private TextView tvTitle;
private TextView tvContent;
private TextView tvCancel;
private TextView tvSure;
private String title, content, cancelString, sureString;
public interface OnViewClickLiatener {
void sureClick();
void cancelClick();
}
public OnViewClickLiatener onViewClickLiatener;
public void setOnViewClickLiatener(OnViewClickLiatener onViewClickLiatener) {
this.onViewClickLiatener = onViewClickLiatener;
}
public ConfirmDialog(Context context) {
this(context, R.style.custom_dialog);
}
public ConfirmDialog(Context context, int themeResId) {
super(context, themeResId);
this.context = context;
}
public ConfirmDialog(Context context, int themeResId, String title, String content, String cancelString, String sureString) {
super(context, themeResId);
this.context = context;
this.title = title;
this.content = content;
this.cancelString = cancelString;
this.sureString = sureString;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_confirm);
setCanceledOnTouchOutside(true);
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = (int) (ScreenUtils.getScreenWidth((Activity) context) * 0.8f);
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
getWindow().setGravity(Gravity.CENTER);
getWindow().setAttributes(params);
getWindow().setBackgroundDrawableResource(R.color.trans);
initView();
setData();
}
public void initView() {
tvTitle = (TextView) findViewById(R.id.tv_title);
tvContent = (TextView) findViewById(R.id.tv_content);
tvCancel = (TextView) findViewById(R.id.tv_cancel);
tvSure = (TextView) findViewById(R.id.tv_sure);
}
public void setData() {
if (!TextUtils.isEmpty(title)) {
tvTitle.setText(title);
}
if (!TextUtils.isEmpty(content)) {
tvContent.setText(content);
}
if (!TextUtils.isEmpty(cancelString)) {
tvCancel.setText(cancelString);
}
if (!TextUtils.isEmpty(sureString)) {
tvSure.setText(sureString);
}
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
if (onViewClickLiatener != null) {
onViewClickLiatener.cancelClick();
}
}
});
tvSure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dismiss();
if (onViewClickLiatener != null) {
onViewClickLiatener.sureClick();
}
}
});
}
@Override
public void dismiss() {
super.dismiss();
}
}
use
/**
* 确认取消提示
*/
ConfirmDialog showCancelDialog;
public void showCancelDialog(String reportOrderNo, String storeCode) {
if (showCancelDialog == null) {
showCancelDialog = new ConfirmDialog(activity, "取消提醒", "取消后将不再对已添加的内容进行保存", "暂不取消", "确认取消");
showCancelDialog.setOnViewClickLiatener(new ConfirmDialog.OnViewClickLiatener() {
@Override
public void sureClick() {
if (TextUtils.isEmpty(reportOrderNo)) {
activity.finish();
} else {
httpReportOrderCancel(reportOrderNo, storeCode);
}
}
@Override
public void cancelClick() {
}
});
}
if (!showCancelDialog.isShowing()) {
showCancelDialog.show();
}
}
3.4 Set the dialog that considers the location, the following rendering is in the upper right corner of the screen, and there is an offset distance
The root is the same as the normal Dialog, but a view needs to be passed in the constructor, that is, for that view to pop up, the offset position of the Dialog is set by obtaining the position of the view on the screen. The following example
public class OtherUserMainMoreDialog extends Dialog {
private DialogViewListener listener;
private Activity mContext;
private View locationView;
private LinearLayout llRemarks;
private LinearLayout llPullBlack;
private LinearLayout llDeleteFriend;
public interface DialogViewListener {
void remarksClick();
void pullBlackClick();
void deleteFriend();
}
public OtherUserMainMoreDialog(Activity context) {
super(context);
mContext = context;
}
public void setDialogViewListener(DialogViewListener listener) {
this.listener = listener;
}
public OtherUserMainMoreDialog(Activity context, int themeResId, View locationView) {
super(context, themeResId);
mContext = context;
this.locationView = locationView;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_other_more, null);
setContentView(view);
//设置Dialog点击外部消失
setCanceledOnTouchOutside(true);
setCancelable(true);
//获取控件 textview 的绝对坐标,( y 轴坐标是控件上部到屏幕最顶部(不包括控件本身))
//location [0] 为x绝对坐标;location [1] 为y绝对坐标
int[] location = new int[2];
locationView.getLocationInWindow(location); //获取在当前窗体内的绝对坐标
//获取当前Activity所在的窗体
Window window = getWindow();
WindowManager.LayoutParams wlp = window.getAttributes();
//获取通知栏高度 重要的在这,获取到通知栏高度
int notificationBar = Resources.getSystem().getDimensionPixelSize(
Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android"));
wlp.x = location[0];//对 dialog 设置 x 轴坐标
wlp.y = location[1] + locationView.getHeight() - notificationBar - 15; //对dialog设置y轴坐标
wlp.gravity = Gravity.TOP;
wlp.width = WindowManager.LayoutParams.MATCH_PARENT;
window.setAttributes(wlp);
llRemarks = (LinearLayout) findViewById(R.id.ll_remarks);
llPullBlack = (LinearLayout) findViewById(R.id.ll_pull_black);
llDeleteFriend = (LinearLayout) findViewById(R.id.ll_delete_friend);
llPullBlack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.pullBlackClick();
}
cancel();
}
});
llRemarks.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.remarksClick();
}
cancel();
}
});
llDeleteFriend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.deleteFriend();
}
cancel();
}
});
}
}
3.5 Notes on using DIalog:
Since DIalog must depend on an Activity, if the Activity is accidentally destroyed, the Dialog will pop up or the message will not find the Activity, resulting in a crash. The solution is as follows:
- Set the Activity as a weak reference so that when the Activity is destroyed, the object holding the Activity can be recycled in time.
- Determine whether the Activity is alive before the Dialog pops up the message, so as to ensure the safe popup or message
Treat it as follows:
@Override
public void dismiss() {
if (context == null || ((Activity) context).isDestroyed() || ((Activity) context).isFinishing()) {
return;
}
super.dismiss();
}
@Override
public void show() {
if (context == null || ((Activity) context).isDestroyed() || ((Activity) context).isFinishing()) {
return;
}
super.show();
}
Fourth, the use of Toast
4.1 The easiest to use, call the system api
Toast.makeText(context, "提示消息", Toast.LENGTH_SHORT).show();
4.2 Set the position of Toast, top, middle, bottom, etc.
Toast toast = Toast.makeText(context, "提示消息", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
4.3 Control the pop-up frequency in a short time
private static String oldMsg;
protected static Toast toast = null;
private static long oneTime = 0;
private static long twoTime = 0;
public static void showToast(Context context, String s, int gravity, int offX, int offY) {
if (toast == null) {
toast = Toast.makeText(context, s, Toast.LENGTH_SHORT);
toast.setGravity(gravity, offX, offY);
toast.show();
oneTime = System.currentTimeMillis();
} else {
twoTime = System.currentTimeMillis();
if (s.equals(oldMsg)) {
if (twoTime - oneTime > Toast.LENGTH_SHORT) {
toast.show();
}
} else {
oldMsg = s;
toast.setText(s);
toast.show();
}
}
oneTime = twoTime;
}
4.4 Customize Toast layout style
private static TextView textView;
/**
* 自定义样式的吐司
* <p/>
* 静态toast 只创建一个toast实例 可以实时显示弹出的内容
*
* @param context
* @param text
*/
public static void showPicToast(Context context, String text) {
if (toast == null) { // 1. 创建前 2.消失后toast为null
// 获取打气筒
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//创建视图
View view = inflater.inflate(R.layout.toast_bg, null);
textView = (TextView) view.findViewById(R.id.tv_toast_text);
//创建土司
toast = new Toast(context);
//设置居中方式 默认在底部
//toast.setGravity(Gravity.CENTER, 0, 0);//如果不设置剧中方式,使用系统默认的吐司位置
//设置土司的持续时长
toast.setDuration(Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
//设置土司的背景View
toast.setView(view);
}
//设置土司的显示额内容
textView.setText(text);
toast.show();
}
4.5 Notes on use:
After Android 30, the Toast position parameter will be invalid, and the set position will follow the system position, so Google recommends replacing Toast with SnackBar.
If you insist on using Toast, then recommend a Toast library, you can set the Toast location, and add the dependent library as follows
implementation 'com.hjq:toast:8.8'
Initialize in application
ToastUtils.init(this);
Pop up the Toast in other places
ToastUtils.show("提示消息");
Five SnackBar
5.1
5.2 Easy to use
public void snackbar1(View view) {
Snackbar.make(this,llRootLayout,"snack bar",Snackbar.LENGTH_SHORT).show();
}
The first parameter is Context,
the second parameter is the view to be displayed,
the third parameter is the string to be displayed
, and the fourth parameter is the display duration. There are three types of duration:
Snackbar.LENGTH_SHORT and Toast.LENGHT_SHORT (about 1 second more ) will automatically disappear after a short duration of display.
Snackbar.LENGTH_LONG is the same as Toast.LENGHT_LONG (about 3 seconds) and
will automatically disappear after a relatively long period of time.
5.3 Interactive use
public void snackbar2(View view) {
Snackbar snack_bar = Snackbar.make(this,view, "确定退出吗?", Snackbar.LENGTH_INDEFINITE);
snack_bar.setAction("确认", new View.OnClickListener() {
@Override
public void onClick(View v) {
//退出
}
});
snack_bar.show();
}
5.4 Custom layout SnackBar
layout snackbar_view.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#000000">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:textColor="@color/black"
android:textSize="11sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="12dp"
android:layout_marginRight="12dp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/textView" />
<TextView
android:id="@+id/textViewSub"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:gravity="center"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:text=""
android:textColor="#ffffff"
android:textSize="11sp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Tool class SnackBarUtil.java
public class SnackBarUtil {
//自定义 SnackBar 布局
public static void show(Activity activity, View view, String msg, String action, SnackBarOnClick listener) {
//获取示例 findViewById(android.R.id.content) //LENGTH_LONG/LENGTH_SHORT: 会自动消失 LENGTH_INDEFINITE: 需要手动点击消失
Snackbar snackbar = Snackbar.make(view, "", Snackbar.LENGTH_SHORT);
//设置 Snackbar 的深度,避免被其他控件遮挡
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
snackbar.getView().setElevation(0);
}
//设置背景透明,避免自带黑色背景影响
snackbar.getView().setBackgroundColor(Color.TRANSPARENT);
//设置padding 取消自定义时黑色边框
snackbar.getView().setPadding(0, 0, 0, 0);
Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) snackbar.getView();
//设置SnackBar的显示位置
//ViewGroup.LayoutParams layoutParams = snackbarLayout.getLayoutParams();
FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams(dip2px(activity,260),dip2px(activity,32)); // 将原来Snackbar的宽高传入新的LayoutParams
flp.gravity = Gravity.CENTER | Gravity.BOTTOM; // 设置显示位置
flp.bottomMargin = dip2px(activity,8);
((View) snackbarLayout).setLayoutParams(flp);
//获取自定义布局
View inflate = LayoutInflater.from(activity).inflate(R.layout.snackbar_view, null);
//获取布局内控件
TextView textView = inflate.findViewById(R.id.textView);
//TextView 前边添加图片
//Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher_round);//图片自己选择
//drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
//textView.setCompoundDrawables(drawable, null, null, null);
//增加文字和图标的距离
//textView.setCompoundDrawablePadding(20);
//设置文本
textView.setText(msg);
if (action != null && listener != null) {
TextView textViewSub = inflate.findViewById(R.id.textViewSub);
textViewSub.setVisibility(View.VISIBLE);
textViewSub.setText(action);
textViewSub.setOnClickListener(v -> {
if (listener != null) {
listener.clickEvent(snackbar);
}
});
}
//添加图片 获取布局内控件
//ImageView imageView = inflate.findViewById(R.id.imageView2);
//获取图片资源
//Drawable drawable = activity.getResources().getDrawable(closeIcon);
//设置图片
//imageView.setImageDrawable(drawable);
//将自定义布局添加到 Snackbar 中
snackbarLayout.addView(inflate);
//显示
snackbar.show();
}
public interface SnackBarOnClick {
void clickEvent(Snackbar snackbar);
}
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Activity activity, float dpValue) {
final float scale = activity.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
Call tool class SnackBarUtil
public void snackbar3(View view) {
SnackBarUtil.show(this, view, "确定退出吗?", "确认", new SnackBarUtil.SnackBarOnClick() {
@Override
public void clickEvent(Snackbar snackbar) {
//退出
}
});
}
Six PopWindow drop-down box use
6.1 PopWindow is also a pop-up box. Compared with Dialog, it is more used in the pop-up based on a certain control position, and also supports arbitrary layout and style.
6.2 Example, add layout file, popup_size_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/dp_80"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcl_view"
android:layout_width="@dimen/dp_80"
android:layout_height="wrap_content" />
</RelativeLayout>
6.3 Customize PopupWindow
public class PopupviewSizeModel extends PopupWindow {
private IPopuWindowListener mOnClickListener;
private Activity mContext;
private RecyclerView recyclerView;
private PopupModelListAdapter popupModelListAdapter;
private List<InfoBean.BindSizeListDTO> listString=new ArrayList<>();
/**
* 暴露给外面的设置单击事件
*/
public void setPopuWindowListener(IPopuWindowListener mOnClickListener) {
this.mOnClickListener = mOnClickListener;
}
public PopupviewSizeModel(Activity context) {
super(context);
this.mContext = context;
//获取布局文件
View mContentView = LayoutInflater.from(mContext).inflate(R.layout.popup_size_listview, null);
initView(mContentView);
//设置布局
setContentView(mContentView);
int width = context.getWindowManager().getDefaultDisplay().getWidth();
setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
//设置可以点击外部消息
//开始
setOutsideTouchable(true);
setFocusable(true);
// setBackgroundDrawable(new BitmapDrawable());
setBackgroundDrawable(context.getResources().getDrawable(android.R.color.transparent));
setAnimationStyle(R.style.pop_animation);
}
private void initView(View contentView) {
recyclerView = (RecyclerView) contentView.findViewById(R.id.rcl_view);
LinearLayoutManager manager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(manager);
recyclerView.setNestedScrollingEnabled(false);
popupModelListAdapter = new PopupModelListAdapter(mContext, R.layout.item_popup_size_list, listString);
recyclerView.setAdapter(popupModelListAdapter);
popupModelListAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
dismiss();
if(mOnClickListener!=null){
mOnClickListener.onItemClick(position);
}
}
@Override
public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
return false;
}
});
}
public void setListData(List<InfoBean.BindSizeListDTO> list) {
listString.clear();
listString.addAll(list);
popupModelListAdapter.setData(listString);
popupModelListAdapter.notifyDataSetChanged();
}
// /***
// * 在android7.0上,如果不主动约束PopuWindow的大小,比如,设置布局大小为 MATCH_PARENT,那么PopuWindow会变得尽可能大,以至于 view下方无空间完全显示PopuWindow,而且view又无法向上滚动,此时PopuWindow会主动上移位置,直到可以显示完全。
// * 解决办法:主动约束PopuWindow的内容大小,重写showAsDropDown方法:
// * @param anchor
// */
// @Override
// public void showAsDropDown(View anchor,int xoff,int yoff,int gravity) {
// if (Build.VERSION.SDK_INT >= 24) {
// Rect visibleFrame = new Rect();
// anchor.getGlobalVisibleRect(visibleFrame);
// int height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom;
// setHeight(height);
// showAsDropDown(anchor, xoff, yoff,gravity);
// } else {
// showAsDropDown(anchor, xoff, yoff,gravity);
// }
// super.showAsDropDown(anchor);
// }
public interface IPopuWindowListener {
void onItemClick(int position);
}
}
6.4 Setting up the data model
publicclass BindSizeListDTO{
public String id;
public String name;
public BindSizeListDTO(String name) {
this.name = name;
}
}
6.5 Pop up the PopupWindow at the specified view position
private PopupviewSizeModel popupviewModelSize;
List<InfoBean.BindSizeListDTO> listStringSize = new ArrayList<>();
private void showSizePopup() {
listStringSize.add(new InfoBean.BindSizeListDTO("230x150"));
listStringSize.add(new InfoBean.BindSizeListDTO("270x200"));
listStringSize.add(new InfoBean.BindSizeListDTO("300x200"));
listStringSize.add(new InfoBean.BindSizeListDTO("330x225"));
listStringSize.add(new InfoBean.BindSizeListDTO("340x239"));
if (popupviewModelSize == null) {
popupviewModelSize = new PopupviewSizeModel(mContext);
popupviewModelSize.setPopuWindowListener(new PopupviewSizeModel.IPopuWindowListener() {
@Override
public void onItemClick(int position) {
Toast.makeText(SnackBarActivity.this, "点击了条目", Toast.LENGTH_SHORT).show();
}
});
}
popupviewModelSize.setListData(listStringSize);
popupviewModelSize.showAsDropDown(tvSize);
}
Seven DialogFragment
7.1 Dialog is dependent on the life cycle of Activity. The difference between DialogFragment and Dialog is that it is essentially a Fragment, which also has the life cycle owned by Fragment.
7.1 The way to create DialogFragment, use onCreateDialog to create the Dialog provided by the system
public class SystemDialogFragment extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog dialog = new AlertDialog.Builder(getContext())
.setTitle("系统弹窗")
.setMessage("信息")
//.setIcon(R.drawable.assign_set_question_ic_v2)
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), "确认", Toast.LENGTH_SHORT).show();
}
}).create();
return dialog;
}
}
Call the DialogFragment in the Activity
public class DialogFragmentActivity extends ComponentActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activty_dialog_fragment);
}
public void alertdialog(View view) {
SystemDialogFragment systemDialogFragment=new SystemDialogFragment();
systemDialogFragment.show(getFragmentManager(),"ss");
}
}
Effect:
7.2 Custom layout DialogFragment
Create a layout file dialog_confirm.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical"
android:paddingLeft="25dp"
android:paddingTop="20dp"
android:paddingRight="25dp"
android:paddingBottom="20dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="退出提示"
android:textColor="#333333"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="15dp"
android:gravity="center"
android:text="是否对本地编辑的内容进行保存?"
android:textColor="#333333"
android:textSize="14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:gravity="center"
android:paddingTop="9dp"
android:paddingBottom="9dp"
android:text="取消"
android:textColor="#666666"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:gravity="center"
android:paddingTop="9dp"
android:paddingBottom="9dp"
android:text="立即充值"
android:textColor="#000000"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
Create DialogFragment, CustomerDialogFragment.java
public class CustomerDialogFragment extends DialogFragment {
public View mRootView;
private TextView tvTitle;
private TextView tvContent;
private TextView tvCancel;
private TextView tvSure;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (mRootView == null){
//获取布局
mRootView = inflater.inflate(R.layout.dialog_confirm,container,false);
}
tvTitle = (TextView) mRootView.findViewById(R.id.tv_title);
tvContent = (TextView) mRootView.findViewById(R.id.tv_content);
tvCancel = (TextView) mRootView.findViewById(R.id.tv_cancel);
tvSure = (TextView) mRootView.findViewById(R.id.tv_sure);
tvCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
tvSure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(), "点击确定", Toast.LENGTH_SHORT).show();
dismiss();
}
});
return mRootView;
}
}
Activity calls the DialogFragment
public void customerdialog(View view) {
CustomerDialogFragment systemDialogFragment=new CustomerDialogFragment();
systemDialogFragment.show(getFragmentManager(),"Customer");
}
Effect demonstration
Eight system suspension frame
8.1 The system floating frame follows the application life cycle, it may not be above Acitivity, does not depend on Acitivity, and is suitable for the pop-up frame of the global life cycle
8.2 Use, create a new layout file, float_layout_window.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linear"
android:layout_width="200dp"
android:orientation="vertical"
android:gravity="center"
android:background="@color/purple_200"
android:layout_height="200dp">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:text="移动"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:text="移动"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
8.2 Add floating frame permission
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />
8.3 Create a new FloatWindowsActivity.java and add a floating frame layout
public class FloatWindowsActivity extends ComponentActivity {
public WindowManager mWindowManager;
public View mWindowView;
public LinearLayout mText;
public WindowManager.LayoutParams wmParams;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activty_float_windows);
}
public void folatwindows(View view) {
checkFloatPermission();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==0){
checkFloatPermission();
}
}
/**
* 检查是否开启悬浮框权限
*/
public void checkFloatPermission(){
if(!Settings.canDrawOverlays(FloatWindowsActivity.this)) {
Toast.makeText( FloatWindowsActivity.this, "当前无权限,请授权", Toast.LENGTH_SHORT);
startActivityForResult( new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse( "package:"+ getPackageName())), 0);
}else {
initWindowParams();
}
}
/**
* 初始化Window对象的参数
*/
private void initWindowParams() {
//1,获取系统级别的WindowManager
mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);
wmParams = new WindowManager.LayoutParams();
//2,添加系统参数,确保悬浮框能显示到手机上
//电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
}
// flag 设置 Window 属性
wmParams.flags
|= WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//期望的位图格式。默认为不透明
wmParams.format = PixelFormat.TRANSLUCENT;
//不许获得焦点
wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//窗口停靠位置
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
addWindowViewZWindow();
initClick();
}
/**
* 添加View到桌面Window界面上
*/
private void addWindowViewZWindow() {
if(mWindowView==null){
mWindowView = LayoutInflater.from(getApplication()).inflate(R.layout.float_layout_window, null);
mText = (LinearLayout) mWindowView.findViewById(R.id.linear);
}
mWindowManager.addView(mWindowView, wmParams);
}
/**
* 点击事件和拖拽事件
*/
int mStartX, mStartY;
int mEndX, mEndY;
private void initClick() {
mText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
//按下鼠标的时候记录下屏幕的位置
case MotionEvent.ACTION_DOWN:
mStartX = (int) event.getRawX();
mStartY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
mEndX = (int) event.getRawX();
mEndY = (int) event.getRawY();
if (needIntercept()) {
//getRawX是触摸位置相对于整个屏幕的位置,getX是控触摸点相对于控件最左边的位置
wmParams.x = (int) event.getRawX() - mWindowView.getMeasuredWidth() / 2;
wmParams.y = (int) event.getRawY() - mWindowView.getMeasuredHeight() / 2;
mWindowManager.updateViewLayout(mWindowView, wmParams);
return true;
}
break;
case MotionEvent.ACTION_UP:
if (needIntercept()) {
return true;
}
break;
}
return false;
}
});
mText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(FloatWindowsActivity.this, "点击悬浮框", Toast.LENGTH_SHORT).show();
}
});
}
/**
* 判断是否拦截,根据滑动的距离
*
* @return
*/
private boolean needIntercept() {
if (Math.abs(mStartX - mEndX) > 30 || Math.abs(mStartY - mEndY) > 30) {
return true;
}
return false;
}
}
8.4 Rendering
Can be displayed in any Activity
You can also return to the desktop and still display