通常我们使用actionbar的话,可以使用overflow按钮弹出所需菜单;但是有时我们需要自定义布局或者自定义标题栏,这时如果想要达到overflow的按钮菜单效果,就可以使用Dialog去自定义菜单了。
通常Dialog包括几个最基本的布局框架(标题栏、信息、按钮),而根据我们的需求,我们可以去除标题栏、按钮;中间的信息可以使用listview来显示菜单item;而使用的style样式如下:
<style name="DialogWithoutTitle" parent="@android:style/Theme.Dialog">
<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@null</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
其中windowNoTitle---无标题以及windowBackground---无背景比较关键,否则就达不到我们需要的样式;
后续我们就可以使用自定义布局了,其中主要代码片段如下:
/*当然这里我们也可以使用LayoutInflater加载需要的布局*/
private View createActionMenuView() {
RelativeLayout parent = new RelativeLayout(mContext);
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int statusAndTitleHeight = mHeadLayoutHeight;
RelativeLayout.LayoutParams parentParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
parent.setLayoutParams(parentParams);
parent.setBackgroundColor(mContext.getResources().getColor(R.color.background_primary));
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
if (mIsShowDialogPartial) {
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.x = metrics.widthPixels / 2;
localLayoutParams.y = statusAndTitleHeight;
} else {
localLayoutParams.gravity = Gravity.FILL_HORIZONTAL | Gravity.TOP;
}
getWindow().setAttributes(localLayoutParams);
ListView list = new ListView(mContext);
LayoutParams listParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
if (mIsShowDialogPartial) {
listParams.width = metrics.widthPixels / 2;
}
list.setLayoutParams(listParams);
fillAdapterData();
setListAdapter(list);
list.setDivider(mContext.getResources().getDrawable(R.drawable.hw_list_divider));
parent.addView(list);
parent.startAnimation(createTranslationInAnimation());
list.startAnimation(createAlphaInAnimation());
return parent;
}
其中通过
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
获取到window并设置window属性;可以设置dialog出现的位置;startAnimation是设置dialog出现时候的动画效果。
另外,我们需要dialog消失的时候,也添加相应的动画,可以重写Dismiss函数:
@Override
public void dismiss() {
if (mCustomView.getAnimation() != null && mCustomView.getAnimation().hasStarted()) {
return;
}
mCustomView.startAnimation(outAnimation);
}
这里需要注意,不能在Dismiss中调用super.dismiss();否则设置的动画会不起作用,我们可以在动画结束的时候调用super.dismiss();
其他的定义interface,实现回调什么的就不写了,直接贴源码:
package com.example.switchfragment;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PopMenu extends Dialog {
private static final int TRANSLATE_DURATION = 200;
private static final int TRANSLATE_DURATION_NA = 1;
private Context mContext;
private int mHeadLayoutHeight;
private boolean mIsShowDialogPartial;
private String mTitle;
private String mMessage;
private Animation outAnimation;
private View mCustomView;
private DialogListClickListener mDialogListClickListener;
private ArrayList<HashMap<String, Object>> mAdapterData = new ArrayList<HashMap<String, Object>>();
private ArrayList<DialogListItem> mListItems = new ArrayList<DialogListItem>();
public PopMenu(Context context) {
super(context, R.style.MmsDialogWithoutTitle);
mContext = context;
setCanceledOnTouchOutside(true);
outAnimation = createTranslationOutAnimation(true);
}
public PopMenu(Context context, int headHeight, boolean isShowPartial) {
this(context);
mHeadLayoutHeight = headHeight;
mIsShowDialogPartial = isShowPartial;
}
public void addItem(int id, String title) {
mListItems.add(new DialogListItem(id, title));
}
public int getItemCount() {
return mListItems.size();
}
public void setEnable(int id, boolean isEnable) {
for (DialogListItem item : mListItems) {
if (id == item.mId) {
item.mEnable = isEnable;
break;
}
}
}
public int[] getIDList() {
int size = mListItems.size();
int[] IDList = new int[size];
DialogListItem item = null;
for (int i = 0; i < size; i++) {
item = mListItems.get(i);
IDList[i] = item.mId;
}
return IDList;
}
public void setTitle(String title) {
mTitle = title;
}
public void setMessage(String message) {
mMessage = message;
}
public void setCustomView(View view) {
mCustomView = view;
}
public void showDialog() {
if (mCustomView == null) {
mCustomView = createActionMenuView();
}
setContentView(mCustomView);
show();
}
@Override
public void dismiss() {
if (mCustomView.getAnimation() != null && mCustomView.getAnimation().hasStarted()) {
return;
}
mCustomView.startAnimation(outAnimation);
}
private void onItemClickDismiss() {
if (mCustomView.getAnimation() != null && mCustomView.getAnimation().hasStarted()) {
return;
}
mCustomView.startAnimation(outAnimation);
}
private void internalDismiss() {
super.dismiss();
}
private Animation createTranslationOutAnimation(boolean animation) {
int type = TranslateAnimation.RELATIVE_TO_SELF;
TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, 0, type, -1);
an.setDuration(animation ? TRANSLATE_DURATION : TRANSLATE_DURATION_NA);
an.setFillAfter(true);
an.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
internalDismiss();
}
});
return an;
}
/*当然这里我们也可以使用LayoutInflater加载需要的布局*/
private View createActionMenuView() {
RelativeLayout parent = new RelativeLayout(mContext);
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int statusAndTitleHeight = mHeadLayoutHeight;
RelativeLayout.LayoutParams parentParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
parent.setLayoutParams(parentParams);
parent.setBackgroundColor(mContext.getResources().getColor(R.color.background_primary));
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
if (mIsShowDialogPartial) {
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.x = metrics.widthPixels / 2;
localLayoutParams.y = statusAndTitleHeight;
} else {
localLayoutParams.gravity = Gravity.FILL_HORIZONTAL | Gravity.TOP;
}
getWindow().setAttributes(localLayoutParams);
ListView list = new ListView(mContext);
LayoutParams listParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
if (mIsShowDialogPartial) {
listParams.width = metrics.widthPixels / 2;
}
list.setLayoutParams(listParams);
fillAdapterData();
setListAdapter(list);
list.setDivider(mContext.getResources().getDrawable(R.drawable.hw_list_divider));
parent.addView(list);
parent.startAnimation(createTranslationInAnimation());
list.startAnimation(createAlphaInAnimation());
return parent;
}
private Animation createAlphaInAnimation() {
AlphaAnimation an = new AlphaAnimation(0.0f, 1.0f);
an.setDuration(TRANSLATE_DURATION);
return an;
}
private Animation createTranslationInAnimation() {
int type = TranslateAnimation.RELATIVE_TO_SELF;
TranslateAnimation an = new TranslateAnimation(type, 0, type, 0, type, -1, type, 0);
an.setDuration((TRANSLATE_DURATION));
return an;
}
private int getStatusBarHeight(Activity activity) {
if (activity == null) {
return 0;
}
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
return statusBarHeight;
}
private void fillAdapterData() {
mAdapterData.clear();
for (DialogListItem item : mListItems) {
HashMap<String, Object> map = new HashMap<String, Object>(1);
map.put("title", item.mTitle);
mAdapterData.add(map);
}
}
public void setListAdapter(ListView list) {
DialogListAdapter adapter = new DialogListAdapter(mContext, mAdapterData, R.layout.dialog_list_item,
new String[]{"title"}, new int[]{R.id.title});
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
DialogListItem item = (DialogListItem) view.getTag();
if (!item.mEnable) {
return;
}
if (mDialogListClickListener != null) {
mDialogListClickListener.onClick(item.mId);
}
onItemClickDismiss();
}
});
list.setAdapter(adapter);
}
public interface DialogListClickListener {
void onClick(int which);
}
public void setDialogListClickListener(DialogListClickListener l) {
mDialogListClickListener = l;
}
private class DialogListItem {
public int mId;
public String mTitle;
public boolean mEnable = true;
public DialogListItem(int id, String title) {
mId = id;
mTitle = title;
}
}
private class DialogListAdapter extends SimpleAdapter {
public DialogListAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (!mListItems.get(position).mEnable) {
TextView title = (TextView) view.findViewById(R.id.title);
title.setEnabled(false);
}
view.setTag(mListItems.get(position));
return view;
}
}
}