Android:高仿UC浏览器popupWindow菜单栏

在模拟UC浏览器的popupWindow菜单栏的时候遇到了一些问题,自己通过在网上搜索资源,整合,解决了一些。例如在学习别人的代码的时候遇到了第一个标题选中不变色,菜单栏不能够响应menu事件消失等问题,当然模仿的程度还没有达到最好,希望以后可以做的更好。

 上传代码的时候没有注意到,菜单栏再次出现的时候,标题定位有问题,所以在这里的代码进行了修改,但是源代码下载没有改,改的地方在popupmenu里

模仿的效果有 菜单上下推拉效果出现于消失 中间分割线可以随选择而移动的动画 下面的菜单选项也可以移动 但模仿不完全

效果图

 

 

布局代码

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

</RelativeLayout>


popmenu.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"
    android:orientation="vertical" >
    
    <GridView 
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:horizontalSpacing="10dip"
        android:numColumns="3"
        android:stretchMode="columnWidth"
        android:verticalSpacing="10dip"
        />

</LinearLayout>


标题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<String> titles;
	private Context context;
	public TextView[] tv_titles;
	int position = 0;

	public TitleAdapter(List<String> 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<String> item_names;
	private List<Integer> item_images;
	private Context context;
	
	public BodyAdapter(Context context,List<String> item_names,List<Integer> 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<String> titles,
			final List<List<String>> item_names, List<List<Integer>> 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<String> 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<String> titles;
	private List<List<String>> item_names; // 选项名称
	private List<List<Integer>> item_images; // 选项图标
	private MyPopupMenu myPopupMenu;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		/**
		 * 菜单栏分类标题
		 */
		titles = new ArrayList<String>();
		titles = addItems(new String[]{"常用", "设置", "工具"});

		/**
		 * 选项图标
		 */
		item_images = new ArrayList<List<Integer>>();
		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<List<String>>();
		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<String>
	 * 用于菜单栏中的菜单项图标赋值
	 * @param values
	 * @return
	 */
	private List<String> addItems(String[] values) {

		List<String> list = new ArrayList<String>();
		for (String var : values) {
			list.add(var);
		}

		return list;
	}

	/**
	 * 转换为List<Integer>
	 * 用于菜单栏中的标题赋值
	 * @param values
	 * @return
	 */
	private List<Integer> addItems(Integer[] values) {

		List<Integer> list = new ArrayList<Integer>();
		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

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="300"
        android:fromYDelta="100%p"
        android:toYDelta="0" />

    <alpha
        android:duration="300"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

</set>


popup_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="1000"
        android:fromYDelta="0"
        android:toYDelta="100%p" />

    <alpha
        android:duration="1000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />

</set>


 

res/values/popup_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="PopupAnimation" parent="android:Animation">
        <item name="android:windowEnterAnimation">@anim/popup_enter</item>
        <item name="android:windowExitAnimation">@anim/popup_exit</item>
    </style>

</resources>


源代码下载地址

http://download.csdn.net/detail/u012251822/6501533
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值