DialogFragment
比Dialog优势,具有生命周期,比如旋转屏幕的时候,activity重建,dialog就不会重新创建,由于不是正常销毁的,会造成内存泄漏,而DialogFragment会随着activity的销毁正常销毁,并且旋转屏幕后也会重建
使用方法:
- 如果已经有存在的dialog 就重写onCreateDialog方法,创建已经存在的dialog
- 重写onCreateView直接创建,跟fragment创建一样
但是需要setStyle
1 全屏的DialogFragment
public class DialogFragmentFullScreen extends DialogFragment implements DialogInterface.OnKeyListener {
private DialogFragmentDismissListener mDialogFragmentDismissListener;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(Window.FEATURE_NO_TITLE, R.style.DialogFragmentFullScreen);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getDialog().setOnKeyListener(this);
}
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
// 如果需要动画或处理返回键操作需要重写dismiss方法
if (isCancelable() && keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
finish();
return true;
}
return false;
}
protected void finish() {
dismiss();
}
public void show(FragmentManager fragmentManager) {
this.show(fragmentManager, this.getClass().getSimpleName());
}
public void setDialogFragmentDismissListener(DialogFragmentDismissListener dialogFragmentDismissListener) {
mDialogFragmentDismissListener = dialogFragmentDismissListener;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (mDialogFragmentDismissListener != null) {
mDialogFragmentDismissListener.onDismiss();
}
}
}
非全屏DialogFragment
public class DialogFragmentUnFullScreen extends DialogFragmentFullScreen {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(Window.FEATURE_NO_TITLE, R.style.DialogFragmentUnFullScreen);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Window window = getDialog().getWindow();
if (window != null) {
window.setLayout(getWidth(), WindowManager.LayoutParams.WRAP_CONTENT); //必须手动指定宽高,布局写死100dp也是不起作用的
}
}
protected int getWidth() {
return AppUtils.dp2px(280, getResources().getDisplayMetrics());
}
}
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:textAllCaps">false</item>
</style>
<style name="DialogFragmentFullScreen" parent="AppTheme">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:windowBackground">@color/dialog_alpha_bg</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="colorPrimaryDark">@color/transparent</item>
</style>
<style name="DialogFragmentUnFullScreen" parent="@style/Theme.AppCompat.Light.Dialog">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
PopWindow 嵌套ListView
我写该popWindow工具类主要是项目中如果用到多次的话,将其封装,每次都能直接使用,比较方便,而且格式能够统一
1.首先是布局文件,比较简单,就一个ListView
<?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:orientation="vertical"
android:background="@drawable/pop_back"
>
<ListView
android:id="@+id/pop_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@color/light_gray"
android:dividerHeight="1px"
android:listSelector="@color/transparent"
android:scrollbars="none"
/>
</LinearLayout>
2.其次是ListView里面需要用的Java Bean
public class PopStringItem {
private String id;
private int icon;
private String name;
public PopStringItem(String id,int icon, String name) {
this.id = id;
this.icon = icon;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
}
3.然后是popWindow的实现代码
public class ListPopWindow extends PopupWindow implements View.OnKeyListener {
private List<PopStringItem> itemList;
private LayoutInflater inflater;
private PopListItemClickListener listItemClickListener;
private Window window;
private final WindowManager.LayoutParams params;
public ListPopWindow(Context context, List<PopStringItem> items, PopListItemClickListener listItemClickListener) {
super(context);
init(context);
window = ((Activity) context).getWindow();
params = window.getAttributes();
this.itemList = items;
this.listItemClickListener = listItemClickListener;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.list_pop_window, null);
setContentView(view);
ListView listView = (ListView) view.findViewById(R.id.pop_list);
if (items.size() == 1) {
listView.setDividerHeight(0);
}
MyAdapter adapter = new MyAdapter();
listView.setAdapter(adapter);
listView.setOnKeyListener(this);
listView.setOnItemClickListener(adapter);
}
private void init(Context context) {
int w = context.getResources().getDisplayMetrics().widthPixels;
setWidth(w / 3); //需要显示设置宽高度
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
setFocusable(true);//设置popWindow是否具有获取焦点的能力,默认为false,一般来讲作用不大,但如果里面包含EditText等需要获取焦点的控件必须设置为true
setOutsideTouchable(true);//设置点击外部区域popWindow是否会消失
setBackgroundDrawable(new BitmapDrawable()); //设置popWindow的背景,只有加了该属性之后,setOutsideTouchable才会起作用,而且加了它之后,popWindow对手机的返回键才有响应,点击返回按钮,关闭popWindow,否则就会关闭popWindow所在的Activity
update();
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
dismiss();
return true;
}
@Override
public void showAsDropDown(View anchor) {
params.alpha = 0.5f; //如果popWindow显示的时候想让window背景变透明,就需要这样做
window.setAttributes(params);
super.showAsDropDown(anchor);
}
@Override
public void showAsDropDown(View anchor, int xoff, int yoff) {
params.alpha = 0.5f;
window.setAttributes(params);
super.showAsDropDown(anchor, xoff, yoff);
}
@Override
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
params.alpha = 0.5f;
window.setAttributes(params);
super.showAsDropDown(anchor, xoff, yoff, gravity);
}
@Override
public void dismiss() {
params.alpha = 1f; //设置回来
window.setAttributes(params);
super.dismiss();
}
class MyAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
@Override
public int getCount() {
int ret = 0;
if (itemList != null) {
ret = itemList.size();
}
return ret;
}
@Override
public PopStringItem getItem(int position) {
return itemList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
PopStringItem item = getItem(position);
ViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_pop_list, parent, false);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.text = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
int icon = item.getIcon();
if (icon == 0) {
holder.image.setVisibility(View.GONE);
} else {
holder.image.setVisibility(View.VISIBLE);
holder.image.setImageResource(icon);
}
holder.text.setText(item.getName());
return convertView;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopStringItem item = getItem(position);
if (listItemClickListener != null) {
listItemClickListener.onClick(item);
}
}
class ViewHolder {
ImageView image;
TextView text;
}
}
//一个回调接口,交给使用PopWindow的Activity来处理
public interface PopListItemClickListener {
void onClick(PopStringItem item);
}
}
4.popWindow的使用
//显示
if (popupWindow == null) {
popupWindow = new ListPopWindow(context, items, this);//items要提前赋值,this表示该类实现上面的回调点击事件
}
popupWindow.showAsDropDown();//需要设置参数
//点击事件的回调
@Override
public void onClick(PopStringItem item) {
popupWindow.dismiss();
if (item.getId().equals("")) {
//根据id判断点击哪个item,进行事件处理
}
}