DialogFragment與PopWindow

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,進行事件處理
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章