在模拟UC浏览器的popupWindow菜单栏的时候遇到了一些问题,自己通过在网上搜索资源,整合,解决了一些。例如在学习别人的代码的时候遇到了第一个标题选中不变色,菜单栏不能够响应menu事件消失等问题,当然模仿的程度还没有达到最好,希望以后可以做的更好。
上传代码的时候没有注意到,菜单栏再次出现的时候,标题定位有问题,所以在这里的代码进行了修改,但是源代码下载没有改,改的地方在popupmenu里
模仿的效果有 菜单上下推拉效果出现于消失 中间分割线可以随选择而移动的动画 下面的菜单选项也可以移动 但模仿不完全
效果图
布局代码
activity_main.xml
popmenu.xml
标题adapter
package com.example.mypopupwindow;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.TextView;
public class TitleAdapter extends BaseAdapter {
private List titles;
private Context context;
public TextView[] tv_titles;
int position = 0;
public TitleAdapter(List titles, Context context,int position) {
this.titles = titles;
this.context = context;
tv_titles = new TextView[titles.size()];
this.position = position;
}
@Override
public int getCount() {
return titles.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
/**曾用来在选中标题后改变字体颜色,但发现标题第一项
* 不能响应,暂时未找到解决办法,所以用了其他方式,
* 这里就注释掉了
public void setFocus(int position) {
for (int i = 0; i < getCount(); i++) {
if(i == position){
tv_titles[i].setTextColor(Color.WHITE);
}else{
tv_titles[i].setTextColor(Color.GRAY);
}
}
}
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/**
* 动态添加标题textView控件,并设置布局属性
*/
tv_titles[position] = new TextView(context);
/**
* 设置textView中的字居中
*/
tv_titles[position].setGravity(Gravity.CENTER);
tv_titles[position].setText(titles.get(position));
tv_titles[position].setTextSize(20);
/**
* 设置TextView的大小
*/
tv_titles[position].setLayoutParams(new GridView.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
tv_titles[position].setPadding(0, 20, 0, 10);
/**
* 在选中某一标题后,重新声明adapter对象,通过构造函数给的position
* 确定把哪个标题的字体颜色直接初始化
*/
if(position == this.position){
tv_titles[position].setTextColor(Color.WHITE);
}else{
tv_titles[position].setTextColor(Color.GRAY);
}
return tv_titles[position];
}
}
功能图片adapter
package com.example.mypopupwindow;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class BodyAdapter extends BaseAdapter{
private List item_names;
private List item_images;
private Context context;
public BodyAdapter(Context context,List item_names,List item_images){
this.context = context;
this.item_names = item_names;
this.item_images = item_images;
}
@Override
public int getCount() {
return item_images.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/**
* 设置图标与图标名称的布局
*/
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setGravity(Gravity.CENTER);
/**
* TextView名称
*/
TextView tv_item = new TextView(context);
tv_item.setLayoutParams(new GridView.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
tv_item.setGravity(Gravity.CENTER);
tv_item.setTextColor(Color.WHITE);
tv_item.setPadding(10, 10, 10, 10);
tv_item.setText(item_names.get(position));
/**
* ImageView图标
*/
ImageView img_item = new ImageView(context);
img_item.setLayoutParams(new LayoutParams(50,50));
img_item.setImageResource(item_images.get(position));
layout.addView(img_item);
layout.addView(tv_item);
return layout;
}
}
popupmenu
package com.example.mypopupwindow;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MyPopupMenu extends PopupWindow {
/**
* 菜单栏的整体布局LinearLayout
*/
private LinearLayout linearLayout;
/**
* 菜单栏分类标题布局GridView
*/
private GridView gv_title;
/**
* 菜单栏功能图标与名称GridView
*/
private GridView gv_body;
/**
* 菜单栏功能图标与名称GridView的适配
*/
private BodyAdapter[] bodyAdapter;
/**
* 菜单栏分类标题GridView的适配
*/
private TitleAdapter titleAdapter;
private Context context;
/**
* 当前选中的分类标题
*/
private int currentIndex = 0;
/**
* 上一次选中的分类标题
* 用于选择分类标题时的左右移动动画,判断应该怎样移动
*/
private int preIndex = 0;
/**
* 标题与功能布局中间的分界线
* RelativeLayout + TextView
*/
private RelativeLayout divisionLayout;
/**
* 屏幕宽度
*/
private int screenWidth = 0;
@SuppressWarnings("deprecation")
public MyPopupMenu(Context context, List titles,
final List> item_names, List> item_images) {
super(context);
this.context = context;
/**
* 菜单栏的整体布局LinearLayout初始化
*/
linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
/**
* 获取屏幕宽度
*/
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
screenWidth = wm.getDefaultDisplay().getWidth();
/**
* 分界线布局初始化
*/
divisionLayout = new RelativeLayout(context);
divisionLayout.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, 3));
divisionLayout.setBackgroundColor(Color.DKGRAY);
/**
* 标题布局初始化
*/
gv_title = new GridView(context);
/**
* 用于重新初始化adapter
*/
final List l = titles;
final Context c = context;
titleAdapter = new TitleAdapter(titles, context, currentIndex);
/**
* 设置被选中后,背景颜色不再是系统原有的黄色,改为TRANSPARENT
*/
gv_title.setSelector(new ColorDrawable(Color.TRANSPARENT));
gv_title.setAdapter(titleAdapter);
gv_title.setSelection(0);
/**
* 设置GridView列数
*/
gv_title.setNumColumns(titleAdapter.getCount());
gv_title.setBackgroundColor(Color.TRANSPARENT);
/**
* 选择分类标题时的响应事件
*/
gv_title.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
/**
* 重新初始化adapter,为了改变标题选择颜色
*/
titleAdapter = new TitleAdapter(l, c, position);
preIndex = currentIndex;
currentIndex = position;
gv_title.setAdapter(titleAdapter);
/**
* 分界线布局中的textView跟随选中标题移动位置的,设置为动画效果
*/
divisionTran(position);
/**
* 用于功能图标GridView动画效果
* TranslateAnimation方法中的参数设置暂时不太明确
* 似乎,参数都是相对于控件自身的位置
* 第一个参数是开始位置,第二个是结束位置
* 有时间会弄清楚
*/
Animation translateBody;
if (preIndex < currentIndex) {
translateBody = new TranslateAnimation(screenWidth, 0, 0,
0);
translateBody.setDuration(500);
gv_body.startAnimation(translateBody);
} else if (preIndex > currentIndex) {
translateBody = new TranslateAnimation(-screenWidth, 0, 0, 0);
translateBody.setDuration(500);
gv_body.startAnimation(translateBody);
}
gv_body.setAdapter(bodyAdapter[position]);
}
});
bodyAdapter = new BodyAdapter[item_names.size()];
for (int i = 0; i < item_names.size(); i++) {
bodyAdapter[i] = new BodyAdapter(context, item_names.get(i),
item_images.get(i));
}
gv_body = new GridView(context);
gv_body.setNumColumns(4);
gv_body.setBackgroundColor(Color.TRANSPARENT);
gv_body.setPadding(0, 10, 0, 10);
gv_body.setAdapter(bodyAdapter[0]);
/**
* 选择功能图标时的响应事件
*/
gv_body.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
/**
* 这里只是在控制台输出了一下功能的名称
*/
System.out.println(item_names.get(currentIndex).get(position));
}
});
/**
* 初始化textView位置
*/
divisionTran(0);
/**
* 把三个子布局加入到整体布局中去
*/
linearLayout.addView(gv_title);
linearLayout.addView(divisionLayout);
linearLayout.addView(gv_body);
this.setContentView(linearLayout);
this.setWidth(LayoutParams.MATCH_PARENT);
this.setHeight(LayoutParams.WRAP_CONTENT);
/**
* 以下代码是为了解决,菜单栏出现后,不能响应再次按menu按键使菜单栏消失的问题
* 在这个网址找到的答案http://blog.csdn.net/admin_/article/details/7278402
* 可以自己去看
*/
this.setFocusable(true);
linearLayout.setFocusableInTouchMode(true);
linearLayout.setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_MENU)
&& (MyPopupMenu.this.isShowing())) {
MyPopupMenu.this.dismiss();
/**
* 使菜单栏消失后,再出现时,依然定位在第一个
*/
titleAdapter = new TitleAdapter(l, c, 0);
gv_title.setAdapter(titleAdapter);
gv_body.setAdapter(bodyAdapter[0]);
divisionTran(0);
return true;
}
return false;
}
});
}
/**
* 分界线布局中的textView跟随选中标题移动位置的,设置为动画效果
*/
public void divisionTran(int position) {
/**
* 先移除了RelativeLayout中原有的textView
*/
divisionLayout.removeAllViews();
/**
* 重新设置textView布局属性
* 动态改变控件位置 第一步
*/
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
screenWidth / 3, LayoutParams.MATCH_PARENT);
/**
* 设置动画效果
*/
Animation translateTextView;
translateTextView = new TranslateAnimation((preIndex-currentIndex) * screenWidth / 3,
0, 0, 0);
/**
* 根据选中的标题确定布局
* 动态改变控件位置 第二步
*/
if (position == 0) {
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
} else if (position == 1) {
lp.addRule(RelativeLayout.CENTER_HORIZONTAL, RelativeLayout.TRUE);
} else {
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
}
/**
* 动态改变控件位置 第三步
*/
TextView line = new TextView(context);
line.setBackgroundColor(Color.WHITE);
divisionLayout.addView(line, lp);
/**
* 设置动画执行时间
*/
translateTextView.setDuration(200);
/**
* 启动动画
*/
line.startAnimation(translateTextView);
}
}
主界面
package com.example.mypopupwindow;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
public class MainActivity extends Activity {
private List titles;
private List> item_names; // 选项名称
private List> item_images; // 选项图标
private MyPopupMenu myPopupMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/**
* 菜单栏分类标题
*/
titles = new ArrayList();
titles = addItems(new String[]{"常用", "设置", "工具"});
/**
* 选项图标
*/
item_images = new ArrayList>();
item_images.add(addItems(new Integer[] { R.drawable.ic_action_call,
R.drawable.ic_action_camera, R.drawable.ic_action_copy,
R.drawable.ic_action_crop, R.drawable.ic_action_cut,
R.drawable.ic_action_discard, R.drawable.ic_action_download,
R.drawable.ic_action_edit }));
item_images.add(addItems(new Integer[] { R.drawable.ic_action_email,
R.drawable.ic_action_full_screen, R.drawable.ic_action_help,
R.drawable.ic_action_important, R.drawable.ic_action_map,
R.drawable.ic_action_mic, R.drawable.ic_action_picture,
R.drawable.ic_action_place }));
item_images.add(addItems(new Integer[] { R.drawable.ic_action_refresh,
R.drawable.ic_action_save, R.drawable.ic_action_search,
R.drawable.ic_action_share, R.drawable.ic_action_switch_camera,
R.drawable.ic_action_video, R.drawable.ic_action_web_site,
R.drawable.ic_action_screen_rotation }));
/**
* 选项名称
*/
item_names = new ArrayList>();
item_names.add(addItems(new String[] { "电话", "相机", "复制", "裁剪", "剪切",
"删除", "下载", "编辑" }));
item_names.add(addItems(new String[] { "邮件", "全屏", "帮助", "收藏", "地图",
"语音", "图片", "定位" }));
item_names.add(addItems(new String[] { "刷新", "保存", "搜索", "分享", "切换",
"录像", "浏览器", "旋转屏幕" }));
myPopupMenu = new MyPopupMenu(this, titles, item_names, item_images);
/**
* 设置菜单栏推拉动画效果
* res/anim中的xml文件与res/values中的popupAnimation.xml一起使用
*/
myPopupMenu.setAnimationStyle(R.style.PopupAnimation);
}
/**
* 转换为List
* 用于菜单栏中的菜单项图标赋值
* @param values
* @return
*/
private List addItems(String[] values) {
List list = new ArrayList();
for (String var : values) {
list.add(var);
}
return list;
}
/**
* 转换为List
* 用于菜单栏中的标题赋值
* @param values
* @return
*/
private List addItems(Integer[] values) {
List list = new ArrayList();
for (Integer var : values) {
list.add(var);
}
return list;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/**
* 系统菜单必须要加一个,才有效果
*/
menu.add("menu");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
if (myPopupMenu.isShowing()) {
myPopupMenu.dismiss();
} else {
/**
* 这句代码可以使菜单栏如对话框一样弹出的效果
* myPopupMenu.setAnimationStyle(android.R.style.Animation_Dialog);
*/
/**
* 设置菜单栏显示位置
*/
myPopupMenu.showAtLocation(findViewById(R.id.layout),
Gravity.BOTTOM, 0, 0);
myPopupMenu.isShowing();
}
return false;
}
}
动画文件 放在res/anim文件夹中 anim文件夹 自己创建
popup_enter.xml
popup_exit.xml
res/values/popup_animation.xml
源代码下载地址