【Android學習】使用popupWindow模擬menu

剛開始學習android,下了個apk,發現它的menu很帥氣,而android自帶的menu非常醜,特別是4.0之後,menu變成了垂直的list,更醜,於是花了點時間模仿了一個

效果圖如下:

源碼下載地址:http://download.csdn.net/detail/cbxjj/7513471

點擊更多按鈕來進行換頁操作

代碼如下:

1.Activity

public class SlideActivity extends Activity {

	private MyMenu_1 myMenu;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	protected void onResume() {
		super.onResume();
		myMenu = new MyMenu_1(SlideActivity.this);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_MENU:
			if (myMenu.isShowing()) {
				myMenu.dismiss();
			} else {
				//將彈出menu顯示到底部
				myMenu.showAtLocation(findViewById(R.id.main_layout),
						Gravity.BOTTOM, 0, 0);
			}
			break;

		case KeyEvent.KEYCODE_BACK:
			myMenu.dismiss();
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
}

2.MyMenu_1

public class MyMenu_1 extends PopupWindow {

	private static int menuSize = 1;
	private Context mContext;
	private RelativeLayout mLinearLayout;
	private GridView mGridView;
	private String[] titles = { "添加收藏夾", "查找短信", "新增短信", "定時任務", "發送報告", "更多", "設置", "關於", "幫助", "反饋", "返回" };
	private int[] images = { R.drawable.icon_menu_favorite,
			R.drawable.icon_menu_search, R.drawable.icon_menu_add,R.drawable.icon_menu_schedule_task,
			R.drawable.icon_menu_view_sent_status,R.drawable.icon_menu_more,R.drawable.icon_menu_setting,
			R.drawable.icon_menu_info,R.drawable.icon_menu_help,R.drawable.icon_menu_feedback,R.drawable.icon_menu_back};
	private List<HashMap<String,Object>> itemList = new ArrayList<HashMap<String,Object>>();
	private SimpleAdapter adapter;
	private LayoutInflater inflater;
	
	public MyMenu_1(Context context){
		super(context);
		
		mContext = context;
		
		initDatas();
		initViewInWin();

		this.setWidth(LayoutParams.FILL_PARENT);
		this.setHeight(LayoutParams.WRAP_CONTENT);
		//這裏用上了我們在popupWindow中定義的animation了
		this.setAnimationStyle(android.R.style.Animation_Dialog);  
		this.setContentView(mLinearLayout); 
		ColorDrawable dw = new ColorDrawable(-00000);
   	    this.setBackgroundDrawable(dw);
		/*設置觸摸外面時消失*/  
		this.setOutsideTouchable(true);
		
		//這裏要設置爲true,否則將無法響應popupWindow中控件的點擊事件。
		this.setFocusable(true);
//		this.update();  
		this.setOnDismissListener(new OnDismissListener() {
			
			@Override
			public void onDismiss() {
				menuSize = 1;
				itemList.clear();
				initDatas();
			}
		});
	}
	
	/**
	 * 初始化popupWindow中的內容
	 */
	public void initViewInWin(){
		inflater = (LayoutInflater)mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
		mLinearLayout = (RelativeLayout)inflater.inflate(R.layout.slide_menu, null);
		
		//這裏需要設置成可以獲取焦點,否則無法響應OnKey事件
		mLinearLayout.setFocusable(true);
		mLinearLayout.setFocusableInTouchMode(true);
		
		//在這裏設置,即可實現關閉的效果。
		mLinearLayout.setOnKeyListener(new LayouOnKeyEvent());
		mGridView = (GridView)mLinearLayout.findViewById(R.id.menu_gridView);
		//設置item點擊響應的時間
		mGridView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if(menuSize == 1 && position == 5){
					MyMenu_1.this.dismiss();
					menuSize = 2;
					itemList.clear();
					initDatas();
					MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
				}				
				if(menuSize == 2 && position == 4){
					MyMenu_1.this.dismiss();
					MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
				}				
			}
		});
		mGridView.setAdapter(adapter);
		
	}
	
	/**
	 * 初始化數據內容
	 */
	public void initDatas(){
		int forStart = 0;
		int forEnd = 5;
		if(menuSize==1){
			forStart = 0;
			forEnd = 5;
		}
		if(menuSize==2){
			forStart = 6;
			forEnd = 6*2-1>titles.length-1?titles.length-1:6*2-1;
		}
		for(int i = forStart; i<=forEnd; i++){
			HashMap<String,Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList.add(map);
		}
		
		adapter = new SimpleAdapter(mContext, itemList, R.layout.my_menu_item,
				new String[]{"image","title"}, new int[]{R.id.item_image,R.id.item_title});
	}
	
	class LayouOnKeyEvent implements OnKeyListener{

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			menuSize = 1;
			itemList.clear();
			initDatas();
			MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
			//判斷事件爲menu按鈕按下時,將popupWindow關閉
			if(event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_MENU){
				if(MyMenu_1.this.isShowing()){
					MyMenu_1.this.dismiss();
				}
			}
			return true;
		}
		
	}
	
	
}

3.slide_menu.xml

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

    <ImageView
        android:id="@+id/gdi_arrow_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/gdi_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/gdi_arrow_up"
        android:background="@drawable/quick_action_top_frame" />

    <GridView
        android:id="@+id/menu_gridView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:fadingEdgeLength="0.0dip"
        android:background="@drawable/quick_action_grid_bg"
        android:horizontalSpacing="10dip"
        android:listSelector="@drawable/quick_action_grid_selector"
        android:numColumns="3"
        android:padding="10dip"
        android:stretchMode="columnWidth"
        android:layout_below="@id/gdi_header"
        android:verticalSpacing="10dip" >
    </GridView>

    <FrameLayout
        android:id="@+id/gdi_footer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/menu_gridView"
        android:background="@drawable/quick_action_grid_bottom_frame" />

    <ImageView
        android:id="@+id/gdi_arrow_down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/gdi_footer" />

</RelativeLayout>

4.my_menu_item.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu_item_layout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
	<ImageView
	    android:id="@+id/item_image"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:focusable="false"
	    android:layout_centerHorizontal="true"
	    />
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:layout_below="@id/item_image"
        android:layout_centerHorizontal="true"
        />
</RelativeLayout>

很順利的做出來了。效果和效果圖一致,基本和apk裏面的差不多,但是我覺得分頁操作不是很方便,覺得android的滾屏左右滑動效果不錯,

用到這個上面也還不錯,於是開始查資料,發現viewPager和viewgroup都可以做,先用viewgroup做了一晚上,各種bug,快崩潰了。

於是換viewPager,中間雖然出了很多次問題,但是還是做出來了,效果如下:



直接上代碼:

1.PopupMenuActivity

public class PopupMenuActivity extends Activity {

	private MyMenu myMenu;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	protected void onResume() {
		super.onResume();
		myMenu = new MyMenu(PopupMenuActivity.this);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_MENU:
			if (myMenu.isShowing()) {
				myMenu.dismiss();
			} else {
				myMenu.showAtLocation(findViewById(R.id.main_layout),
						Gravity.BOTTOM, 0, 0);
			}
			break;

		case KeyEvent.KEYCODE_BACK:
			myMenu.dismiss();
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
}

2.Mymenu.java

public class MyMenu extends PopupWindow {

	private Context mContext;
	private LinearLayout mLinearLayout;
	private LinearLayout pointLLayout;
	private GridView mGridView1;
	private GridView mGridView2;
	private String[] titles = { "添加收藏夾", "查找短信", "新增短信", "定時任務", "發送報告", "更多",
			"設置", "關於", "幫助", "反饋", "返回" };
	private int[] images = { R.drawable.icon_menu_favorite,
			R.drawable.icon_menu_search, R.drawable.icon_menu_add,
			R.drawable.icon_menu_schedule_task,
			R.drawable.icon_menu_view_sent_status, R.drawable.icon_menu_more,
			R.drawable.icon_menu_setting, R.drawable.icon_menu_info,
			R.drawable.icon_menu_help, R.drawable.icon_menu_feedback,
			R.drawable.icon_menu_back };
	private List<HashMap<String, Object>> itemList1 = new ArrayList<HashMap<String, Object>>();
	private List<HashMap<String, Object>> itemList2 = new ArrayList<HashMap<String, Object>>();
	private MySimpleAdapter adapter1;
	private MySimpleAdapter adapter2;
	private LayoutInflater inflater;

	private ImageView[] imgs;
	private int count;
	private int currentItem;

	private MyViewPagerAdapter adapter;
	private MyViewPager viewPager;
	private ArrayList<GridView> array = new ArrayList<GridView>();

	public MyMenu(Context context) {
		super(context);

		mContext = context;

		initDatas();
		initViewInWin();

		this.setWidth(LayoutParams.FILL_PARENT);
		this.setHeight(LayoutParams.WRAP_CONTENT);
		// 這裏用上了我們在popupWindow中定義的animation了
		this.setAnimationStyle(android.R.style.Animation_Dialog);
		this.setContentView(mLinearLayout);
		//必須設置背景色爲透明,不然彈出窗口寬度不全屏
		ColorDrawable dw = new ColorDrawable(-00000);
		this.setBackgroundDrawable(dw);
		/* 設置觸摸外面時消失 */
		this.setOutsideTouchable(true);

		// 這裏要設置爲true,否則將無法響應popupWindow中控件的點擊事件。
		this.setFocusable(true);
		this.update();
		this.setOnDismissListener(new OnDismissListener() {

			@Override
			public void onDismiss() {
				itemList1.clear();
				itemList2.clear();
				initDatas();
			}
		});

		pointLLayout = (LinearLayout) mLinearLayout.findViewById(R.id.llayout);
		viewPager = (MyViewPager) mLinearLayout.findViewById(R.id.myviewpager);
		count = viewPager.getChildCount();
		imgs = new ImageView[count];
		for (int i = 0; i < count; i++) {
			imgs[i] = (ImageView) pointLLayout.getChildAt(i);
			imgs[i].setEnabled(true);
			imgs[i].setTag(i);
		}
		currentItem = 0;
		imgs[currentItem].setEnabled(false);
		viewPager.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int point) {
				setcurrentPoint(point);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int point) {
			}
		});

		adapter = new MyViewPagerAdapter(mContext, array);
		viewPager.setAdapter(adapter);
	}

	protected void setcurrentPoint(int position) {
		if (position < 0 || position > count - 1 || currentItem == position) {
			return;
		}
		imgs[currentItem].setEnabled(true);
		imgs[position].setEnabled(false);
		currentItem = position;
	}

	public void initViewInWin() {
		inflater = (LayoutInflater) mContext
				.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
		mLinearLayout = (LinearLayout) inflater.inflate(R.layout.my_menu, null);
		mLinearLayout.setFocusable(true);
		mLinearLayout.setFocusableInTouchMode(true);

		mLinearLayout.setOnKeyListener(new LayouOnKeyEvent());
		mGridView1 = (GridView) mLinearLayout.findViewById(R.id.menu_gridView1);
		mGridView2 = (GridView) mLinearLayout.findViewById(R.id.menu_gridView2);

		mGridView1.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				System.out.println("點擊第一個第" + position + "個按鈕");
			}
		});
		mGridView1.setAdapter(adapter1);
		mGridView2.setAdapter(adapter2);

		array.add(mGridView1);
		array.add(mGridView2);
	}

	public void initDatas() {
		int forStart = 0;
		int forEnd = 5;
		for (int i = forStart; i <= forEnd; i++) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList1.add(map);
		}

		adapter1 = new MySimpleAdapter(mContext, itemList1,
				R.layout.my_menu_item, new String[] { "image", "title" },
				new int[] { R.id.item_image, R.id.item_title });

		forStart = 6;
		forEnd = 6 * 2 - 1 > titles.length - 1 ? titles.length - 1 : 6 * 2 - 1;

		for (int i = forStart; i <= forEnd; i++) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList2.add(map);
		}
		adapter2 = new MySimpleAdapter(mContext, itemList2,
				R.layout.my_menu_item, new String[] { "image", "title" },
				new int[] { R.id.item_image, R.id.item_title });
	}

	class LayouOnKeyEvent implements OnKeyListener {

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			itemList1.clear();
			itemList2.clear();
			initDatas();
			MyMenu.this.showAtLocation(
					mLinearLayout.findViewById(R.id.menu_item_layout),
					Gravity.BOTTOM, 0, 0);

			// 判斷事件爲menu按鈕按下時,將popupWindow關閉
			if (event.getAction() == KeyEvent.ACTION_DOWN
					&& keyCode == KeyEvent.KEYCODE_MENU) {
				if (MyMenu.this.isShowing()) {
					MyMenu.this.dismiss();
				}
			}
			return true;
		}

	}

}

3.MySimpleAdapter 不用SimpleAdapter 而是自己寫一個,因爲報了一個The observer is null.查了下問題,應該是關閉window的時候setAdapter的時候unregisterDataSetObserver沒判斷mDataSetObserver是否爲空,據說是因爲嵌套控件導致,這裏直接判斷下就完了

public class MySimpleAdapter extends SimpleAdapter {

	public MySimpleAdapter(Context context,
			List<? extends Map<String, ?>> data, int resource, String[] from,
			int[] to) {
		super(context, data, resource, from, to);
	}
	
	@Override
	public void unregisterDataSetObserver(DataSetObserver observer) {
		if (observer != null) {
			super.unregisterDataSetObserver(observer);
		}
	}
	
}

4.MyViewPager 繼承了android.support.v4.view.ViewPager,因爲這個控件高度自動全屏了 設置wrap_content也沒用,這裏集成了ViewPager重新設置了以下高度

public class MyViewPager extends ViewPager {

	public MyViewPager(Context context) {
		super(context);
	}

	public MyViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		int height = 0;
		for (int i = 0; i < getChildCount(); i++) {
			View child = getChildAt(i);
			child.measure(widthMeasureSpec,
					MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
			int h = child.getMeasuredHeight();
			if (h > height)
				height = h;
		}

		heightMeasureSpec = MeasureSpec.makeMeasureSpec(height*2,
				MeasureSpec.EXACTLY);

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
}

5.MyViewPagerAdapter重寫了PagerAdapter

public class MyViewPagerAdapter extends PagerAdapter {
	private List<GridView> array;

	/**
	 * 供外部調用(new)的方法
	 * 
	 * @param context
	 *            上下�?
	 * @param imageViews
	 *            添加的序列對�?
	 */
	public MyViewPagerAdapter(Context context, List<GridView> array) {
		this.array = array;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return array.size();
	}

	@Override
	public boolean isViewFromObject(View arg0, Object arg1) {
		// TODO Auto-generated method stub
		return arg0 == arg1;
	}

	@Override
	public Object instantiateItem(View arg0, int arg1) {
		((ViewPager) arg0).addView(array.get(arg1));
		return array.get(arg1);
	}

	@Override
	public void destroyItem(View arg0, int arg1, Object arg2) {
		((ViewPager) arg0).removeView((View) arg2);
	}

	@Override
	public void unregisterDataSetObserver(DataSetObserver observer) {
		if (observer != null) {
			super.unregisterDataSetObserver(observer);
		}
	}
}

6.my_menu.xml 注意這裏最外層必須用LinearLayout,否則會報一個android.support.v4.view.ViewPager canot be cast to。。。。

轉換異常,用RelativeLayout狂報錯。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/gdi_arrow_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/gdi_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/quick_action_top_frame" />
    
   <RelativeLayout   
	  	android:layout_width="fill_parent"    
	  	android:layout_height="wrap_content"
	  	android:id="@+id/renlayout"
        android:background="@drawable/quick_action_grid_bg"
	  	>
    <com.cbxjj.myplugins.MyViewPager
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:scaleType="fitXY"
        android:layout_gravity="center"
        android:id="@+id/myviewpager">

            <GridView
                android:id="@+id/menu_gridView1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:fadingEdgeLength="0.0dip"
                android:gravity="center"
                android:horizontalSpacing="10dip"
                android:listSelector="@drawable/quick_action_grid_selector"
                android:numColumns="3"
                android:padding="10dip"
                android:stretchMode="columnWidth"
                android:verticalSpacing="10dip" >
            </GridView>
            <GridView
                android:id="@+id/menu_gridView2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:fadingEdgeLength="0.0dip"
                android:gravity="center"
                android:horizontalSpacing="10dip"
                android:listSelector="@drawable/quick_action_grid_selector"
                android:numColumns="3"
                android:padding="10dip"
                android:stretchMode="columnWidth"
                android:verticalSpacing="10dip" >
            </GridView>
   </com.cbxjj.myplugins.MyViewPager>
	<LinearLayout 
    	android:orientation="horizontal" 
    	android:id="@+id/llayout" 
    	android:layout_width="fill_parent" 
    	android:layout_height="15dp" 
        android:layout_below="@id/myviewpager"
    	android:layout_centerHorizontal="true"
    	android:gravity="center"
    	android:visibility="visible">
      
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:clickable="true"
            android:padding="5.0dip"
            android:src="@drawable/page_indicator_bg" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:clickable="true"
            android:padding="5.0dip"
            android:src="@drawable/page_indicator_bg" />
</LinearLayout>
    </RelativeLayout>
    <FrameLayout
        android:id="@+id/gdi_footer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/quick_action_grid_bottom_frame" >
        </FrameLayout>
</LinearLayout>
以上。

源碼下載地址:http://download.csdn.net/detail/cbxjj/7513471



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章