Android之用PopupWindow實現彈出listview形式菜單

 android4.0之前的菜單使用非常廣泛,但是在android4.0之後,很少使用先前的菜單樣式瞭。那如何實現下圖的樣式瞭?

我們簡單模擬一下。
(1)屏蔽系統彈出的菜單: 
 

 1、首先創建至少一個系統的菜單選項

 

[java]
@Override 
   public boolean onCreateOptionsMenu(Menu menu) 
   { 
       menu.add("menu");// 必須創建一項  
       return super.onCreateOptionsMenu(menu); 
   } 
 @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        menu.add("menu");// 必須創建一項
        return super.onCreateOptionsMenu(menu);
    }       2、在onMenuOpened方法裡顯示自己的菜單視圖,並返回FALSE。 註意必須返回false,不然會出現menu選項

[java]
@Override 
  public boolean onMenuOpened(int featureId, Menu menu){ 
 
      switchSysMenuShow(); 
   
      return false;// 返回為true 則顯示系統menu  
   
  } 
  @Override
    public boolean onMenuOpened(int featureId, Menu menu){
 
        switchSysMenuShow();
   
        return false;// 返回為true 則顯示系統menu
   
    }
3、從圖片中可以看出,彈出的是一個listview,所以要按照listview的標準來實現佈局,給出佈局文件。

[html]
<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical"   
    android:paddingLeft="20dip" 
    android:gravity="right" 
    android:id="@+id/hotalk_menu_view_layout" >      
    <!– 顯示的listview –>  
        <ListView android:id="@+id/hotalk_menu_listview" 
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content" 
            android:paddingLeft="7.6dip"     
            android:paddingRight="7.6dip"                    
            android:fadingEdge="none" 
            android:focusable="true" 
            android:longClickable="true" 
            android:scrollbarSize="0sp"         
            android:scrollbarStyle="insideOverlay" 
            android:background="@drawable/menu_bg_popup" 
            android:pider="@drawable/menu_bg_line" 
            android:piderHeight="1px" 
            android:cacheColorHint="#00000000"> 
    </ListView>    
</RelativeLayout> 
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" 
    android:paddingLeft="20dip"
    android:gravity="right"
    android:id="@+id/hotalk_menu_view_layout" >    
    <!– 顯示的listview –>
        <ListView android:id="@+id/hotalk_menu_listview"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:paddingLeft="7.6dip" 
   android:paddingRight="7.6dip"     
   android:fadingEdge="none"
         android:focusable="true"
         android:longClickable="true"
         android:scrollbarSize="0sp"       
         android:scrollbarStyle="insideOverlay"
   android:background="@drawable/menu_bg_popup"
   android:pider="@drawable/menu_bg_line"
   android:piderHeight="1px"
   android:cacheColorHint="#00000000">
 </ListView>  
</RelativeLayout>4、listview的顯示其實就是個textview,給出該佈局文件。

[html]
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"     
    android:gravity="center_vertical" 
    android:background="@drawable/menu_item_bg" 
    android:orientation="vertical" > 
    <!– 顯示內容 –> 
    <TextView 
        android:id="@+id/textview" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:minHeight="40dip" 
        android:layout_marginLeft="12dip" 
        android:layout_marginRight="12dip" 
        android:paddingTop="6dip" 
        android:paddingBottom="6dip" 
        android:textSize="14.7sp" 
        android:gravity="center_vertical" 
        android:textColor="#CCCCCC"  /> 
 
</LinearLayout> 
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"   
    android:gravity="center_vertical"
    android:background="@drawable/menu_item_bg"
    android:orientation="vertical" >
    <!– 顯示內容 –>
    <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:minHeight="40dip"
        android:layout_marginLeft="12dip"
        android:layout_marginRight="12dip"
        android:paddingTop="6dip"
        android:paddingBottom="6dip"
        android:textSize="14.7sp"
        android:gravity="center_vertical"
        android:textColor="#CCCCCC"  />

</LinearLayout>
下面給出實現這個的工具類HotalkMenuView,該類繼承view[java]
package com.jindegege.demo; 
 
import java.util.ArrayList; 
import java.util.Collections; 
import android.content.Context; 
import android.content.res.Configuration; 
import android.graphics.Paint; 
import android.os.Build; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.Display; 
import android.view.Gravity; 
import android.view.KeyEvent; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.WindowManager; 
import android.view.View.OnClickListener; 
import android.view.View.OnKeyListener; 
import android.view.ViewGroup.LayoutParams; 
import android.view.animation.TranslateAnimation; 
import android.view.inputmethod.InputMethodManager; 
import android.widget.ListView; 
import android.widget.PopupWindow; 
import android.widget.RelativeLayout; 
import android.widget.SimpleAdapter; 
import android.widget.TextView; 
 
 
 
public class HotalkMenuView extends View 

    /**
     * 發送短信的模式 hotalk或者短信
     */ 
    public final static int MENU_SEND_MSG_FORMULAR = 0; 
 
    /**
     * 查看聯系人
     */ 
    public final static int MENU_VIEW_CONTACT = 1; 
 
    /**
     * 添加聯系人
     */ 
    public final static int MENU_ADD_CONTACT = 2; 
 
    /**
     * 群成員管理
     */ 
    public final static int MENU_MEMBER_MANAGER = 3; 
 
    /**
     * 批量收藏
     */ 
    public final static int MENU_ADD_TO_FAVORITES = 4; 
 
    /**
     * 批量刪除
     */ 
    public final static int MENU_DELETE_MULTI_MSG = 5; 
 
 
 
    /**
     * 上下文
     */ 
    private Context mContext; 
 
    /**
     * PopupWindow
     */ 
    private PopupWindow popWindow; 
 
    /**
     * 顯示View
     */ 
    private View popview; 
 
    /**
     * listview
     */ 
    public ListView listview; 
 
    /**
     * 填充數據集
     */ 
    public ArrayList<MenuItem> mitems = null; 
 
    /**
     * 設置顯示位置
     */ 
    RelativeLayout layout; 
 
    /**
     * 橫屏菜單距離最大高度
     */ 
    private int bottomLenght_h = 77; 
 
    /**
     * 豎屏菜單距離最大高度
     */ 
    private int bottomLenght_v = 173; 
 
    /**
     * 屏幕密度
     */ 
    private Display display; 
 
    /**
     * 畫板用於測字符寬度
     */ 
    private Paint paint = null; 
 
    /**
     * 菜單中最在的字符寬度
     */ 
    private float maxWeith = 0; 
 
    /**
     * 顯示靠左邊菜單的左邊距
     */ 
    private int rightMenuLeft = 45; 
 
    /**
     * 顯示靠左邊菜單的最大右邊距
     */ 
    private int maxRightWeith = 44; 
 
    /**
     * 顯示靠左邊菜單的最小右邊距
     */ 
    private int minRightWeith = 140; 
 
    /**
     * 菜單的最小左邊距
     */ 
    private int maxLeftWeith = 88; 
 
    /**
     * 菜單的最小左邊距
     */ 
    private int minLeftWeith = 188; 
 
    /**
     * 橫屏菜單最小左邊距
     */ 
    private int maxLeftWeith_h = 282; 
 
    /**
     * 橫屏菜單最小左邊距
     */ 
    private int minLeftWeith_h = 371; 
 
    /**
     * 菜單的背景和文字兩邊占間距
     */ 
    private int contentSpaceWeith = 38; 
 
    /**
     * 打開Menu動畫
     */ 
    private TranslateAnimation myMenuOpen; 
 
    /**
     * 關閉Menu動畫
     */ 
    private TranslateAnimation myMenuClose; 
 
    /**
     * 打開Menu動畫所用時間
     */ 
    private int menuOpenMillis = 500; 
 
    /**
     * 關閉Menu動畫 所用時間
     */ 
    private int menuCloseMillis = 400; 
 
    /**
     * 彈出窗口播放Menu的動畫
     */ 
    private final int MENU_OPEN_ANIM = 1; 
 
    /**
     * 關閉Menu動畫 後關閉窗口
     */ 
    private final int MENU_CLOSE_ANIM = 2; 
 
    /**
     * 當前窗口handler
     */ 
    private MyHandler myHandler = new MyHandler(); 
 
    /**
     * 正在進行關閉Menu操作
     */ 
    private boolean isDismissing = false; 
 
    class MyHandler extends Handler 
    { 
        @Override 
        public void handleMessage(Message msg) 
        { 
            if (msg == null) 
            { 
                return; 
            } 
            super.handleMessage(msg); 
            switch (msg.what) 
            { 
                case MENU_OPEN_ANIM: 
                    startMenuOpenAnimation(); 
                    break; 
                case MENU_CLOSE_ANIM: 
                    if(popWindow!=null){ 
                    popWindow.dismiss(); 
                    } 
                    isDismissing = false; 
                    break; 
            } 
        } 
    } 
 
    public HotalkMenuView(Context context) 
    { 
        super(context); 
        mContext = context; 
        mitems = new ArrayList<MenuItem>(); 
        LayoutInflater layoutInflater = (LayoutInflater) (mContext).getSystemService(mContext.LAYOUT_INFLATER_SERVICE); 
        // 獲取自定義佈局文件的視圖  
        popview = layoutInflater.inflate(R.layout.hotalk_menu_view, null); 
        listview = (ListView) popview.findViewById(R.id.hotalk_menu_listview); 
        layout = (RelativeLayout) popview.findViewById(R.id.hotalk_menu_view_layout); 
        adapter = new ItemTextListAdapter(mContext); 
        popWindow = new PopupWindow(popview, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);//以PopupWindow彈出  
        display = ((WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE)).getDefaultDisplay(); 
        initValue(); 
        layout.setOnClickListener(onclick); 
        listview.setFocusable(false); 
        listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
        listview.setAdapter(adapter); 
        listview.setFocusableInTouchMode(true); 
        listview.setMinimumHeight(200); 
        listview.setOnKeyListener(new OnKeyListener() 
        { 
            @Override 
            public boolean onKey(View v, int keyCode, KeyEvent event) 
            { 
                // 正執行關閉Menu菜單操作將不重復操作  
                if (!isDismissing) 
                { 
                    isDismissing = true; 
                    if ((keyCode == KeyEvent.KEYCODE_MENU) && (popWindow.isShowing())) 
                    { 
                        close(); 
                    } 
                    else if (((keyCode == KeyEvent.KEYCODE_BACK) && (popWindow.isShowing()))) 
                    { 
                        close(); 
                    } 
                } 
 
                return false; 
            } 
        }); 
    } 
 
    /**
     * 初始設置Menu位置參數
     */ 
    private void initValue() 
    { 
        paint = new Paint(); 
        rightMenuLeft = (int) (rightMenuLeft * FusionField.currentDensity); 
        maxLeftWeith = (int) (maxLeftWeith * FusionField.currentDensity); 
        minLeftWeith = (int) (minLeftWeith * FusionField.currentDensity); 
        maxRightWeith = (int) (maxRightWeith * FusionField.currentDensity); 
        minRightWeith = (int) (minRightWeith * FusionField.currentDensity); 
        bottomLenght_h = (int) (bottomLenght_h * FusionField.currentDensity); 
        bottomLenght_v = (int) (bottomLenght_v * FusionField.currentDensity); 
        contentSpaceWeith = (int) (contentSpaceWeith * FusionField.currentDensity); 
        maxLeftWeith_h = (int) (maxLeftWeith_h * FusionField.currentDensity); 
        minLeftWeith_h = (int) (minLeftWeith_h * FusionField.currentDensity); 
    } 
 
    /**
     * 添加菜單項
     * 
     * @param key
     * @param value
     */ 
    public void add(int key, String value) 
    { 
        remove(key);  
        MenuItem item = new MenuItem(key, value); 
        mitems.add(item); 
        adapter.notifyDataSetChanged(); 
 
    } 
 
    /**
     * 添加 菜單項
     * 
     * @param position 位置(必須是按0~n)添加
     * @param key
     * @param value
     */ 
    public void add(int position, int key, String value) 
    { 
        MenuItem item = new MenuItem(key, value); 
        if (position == mitems.size()) 
        { 
            mitems.add(position, item); 
 
            adapter.notifyDataSetChanged(); 
        } 
    } 
 
    /**
     * 獲取文本最大長度
     */ 
    private void getContextMaxLength() 
    { 
        adapter.notifyDataSetChanged(); 
        if (mitems != null && mitems.size() > 0) 
        { 
            maxWeith = 0; 
            if (Build.VERSION.SDK_INT >= 14) 
            { 
                // android 4.0手機當前字體大小自適  
                TextView tv = new TextView(mContext); 
                tv.setTextSize(FusionField.SET_TYPE_TEXT_SIZE); 
                float size = tv.getTextSize() / FusionField.SET_TYPE_TEXT_SIZE; 
                paint.setTextSize((int) ((size * 12) * FusionField.currentDensity)); 
            } 
            else 
            { 
                paint.setTextSize((int) ((FusionField.SET_TYPE_TEXT_SIZE + 1) * FusionField.currentDensity)); 
            } 
 
            for (int i = 0; i < mitems.size(); i++) 
            { 
                if (paint.measureText(mitems.get(i).MenuValue) > maxWeith) 
                { 
                    maxWeith = paint.measureText(mitems.get(i).MenuValue); 
                } 
            } 
        } 
    } 
 
    /**
     * 更新菜單項按位置更新
     * 
     * @param position
     * @param key
     * @param value
     */ 
    public void updateItem(int position, int key, String value) 
    { 
        if (mitems.size() > position) 
        { 
            remover(position); 
            MenuItem item = new MenuItem(key, value); 
            mitems.add(position, item); 
        } 
    } 
 
    /**
     * 刪除菜單項
     * 
     * @param position
     */ 
    public void remover(int position) 
    { 
        if (mitems.size() > position) 
        { 
            mitems.remove(position); 
        } 
    } 
 
    /**
     * 刪除菜單項 add by shaxinajun
     * 
     * @param position
     */ 
    public void remove(int key) 
    { 
        MenuItem item = null; 
        for (int i = 0; i < mitems.size(); i++) 
        { 
            item = mitems.get(i); 
            if (item.MenuKey == key) 
            { 
                mitems.remove(i); 
                break; 
            } 
        } 
    } 
 
    /**
     * 清空菜單項
     */ 
    public void clear() 
    { 
        mitems.clear(); 
        maxWeith = 0; 
    } 
 
    ItemTextListAdapter adapter; 
 
    /**
     * 設置Menu顯示位置,不可以自適應屏幕 密度 方法表述
     * 
     * @param left
     * @param top
     * @param right
     * @param bottom void
     */ 
    public void setMenuPosition(int left, int top, int right, int bottom) 
    { 
        layout.setPadding(left, (int) (46 * FusionField.currentDensity), right, bottom); 
    } 
 
    /**
     * 單擊事件
     */ 
    private OnClickListener onclick = new OnClickListener() 
    { 
        @Override 
        public void onClick(View v) 
        { 
            switch (v.getId()) 
            { 
            // 點擊空白外讓其消失  
                case R.id.hotalk_menu_view_layout: 
                    close(); 
                    break; 
                default: 
                    break; 
            } 
        } 
    }; 
 
    /**
     * 重新設置菜單項
     * 
     * @param list
     */ 
    public void setItems(ArrayList<String> items) 
    { 
        mitems.clear(); 
        if (items != null && items.size() > 0) 
        { 
            for (int i = 0; i < items.size(); i++) 
            { 
                MenuItem item = new MenuItem(0, items.get(i)); 
                mitems.add(item); 
            } 
        } 
    } 
 
    public void setPositionShow() 
    { 
        try 
        { 
            if (popWindow != null && popview != null) 
            { 
                if (popWindow.isShowing()) 
                { 
                    startMenuCloseAnimation(); 
                } 
                else 
                { 
                    getContextMaxLength(); 
                   int right = (int) ((320 * FusionField.currentDensity) – (maxWeith + rightMenuLeft + contentSpaceWeith)); 
                  
                    if (right < maxRightWeith) 
                    { 
                        right = maxRightWeith; 
                    } 
                    else if (right > minRightWeith) 
                    { 
                        right = minRightWeith; 
                    } 
                    //setMenuPosition(rightMenuLeft, 10, right, bottomLenght_v);  
                    setMenuPosition(rightMenuLeft, 0, 0, bottomLenght_v); 
                    Collections.sort(mitems); 
                    // 規定彈窗的位置  
                    popWindow.setFocusable(true); 
                    popWindow.update(); 
                    popWindow.showAtLocation(popview, Gravity.FILL, 0, 0); 
                    myHandler.sendEmptyMessage(MENU_OPEN_ANIM); 
                } 
            } 
        } 
        catch (Exception e) 
        { 
            Log.i("HotalkMenuView", "e:" + e.toString()); 
            close(); 
        } 
    } 
 
    /**
     * 顯示
     */ 
    public void show() 
    { 
        try 
        { 
            if (popWindow != null && popview != null) 
            { 
                if (popWindow.isShowing()) 
                { 
                    startMenuCloseAnimation(); 
                } 
                else 
                { 
                    if (mitems != null && mitems.size() > 0) 
                    { 
                        int orientation = display.getOrientation(); 
                        if (orientation == 0) 
                        {// 豎屏  
                            if (FusionField.currentActivity != null 
                                    && FusionField.currentActivity.getCurrentFocus() != null 
                                    && FusionField.currentActivity.getCurrentFocus().getWindowToken() != null) 
                            { 
                                ((InputMethodManager) FusionField.currentActivity 
                                        .getSystemService(FusionField.currentActivity.INPUT_METHOD_SERVICE)) 
                                        .hideSoftInputFromWindow(FusionField.currentActivity.getCurrentFocus() 
                                                .getWindowToken(), 0); 
                            } 
                            getContextMaxLength(); 
                            int left = (int) ((320 * FusionField.currentDensity) – (maxWeith + contentSpaceWeith)); 
                            if (left < maxLeftWeith) 
                            { 
                                left = maxLeftWeith; 
                            } 
                            else if (left > minLeftWeith) 
                            { 
                                left = minLeftWeith; 
                            } 
                            setMenuPosition(left, 0, 0, bottomLenght_v); 
 
                        } 
                        else 
                        // 橫屏  
                        { 
                            getContextMaxLength(); 
                            int left = (int) ((533 * FusionField.currentDensity) – (maxWeith + contentSpaceWeith)); 
                            Log.i("jindegege", "left:" + left + " rightMenuLeft:" 
                                    + (480 * FusionField.currentDensity)); 
                            if (left < maxLeftWeith_h) 
                            { 
                                left = maxLeftWeith_h; 
                            } 
                            else if (left > minLeftWeith_h) 
                            { 
                                left = minLeftWeith_h; 
                            } 
                            setMenuPosition(left, 0, 0, bottomLenght_h); 
                        } 
                        Collections.sort(mitems); 
                        // 規定彈窗的位置  
                        popWindow.setFocusable(true); 
                        popWindow.update(); 
                        popWindow.showAtLocation(listview, Gravity.FILL, 0, (int) (46 * FusionField.currentDensity)); 
                        myHandler.sendEmptyMessage(MENU_OPEN_ANIM); 
 
                    } 
                } 
            } 
        } 
        catch (Exception e) 
        { 
            Log.i("HotalkMenuView", "show() e:" + e.toString()); 
            close(); 
        } 
    } 
 
    /**
     * 判讀是否顯示
     * 
     * @return boolean
     */ 
    public boolean getIsShow() 
    { 
        return popWindow.isShowing(); 
    } 
 
    /**
     * 關閉
     */ 
    public void close() 
    { 
        if (popWindow != null && popWindow.isShowing()) 
        { 
            startMenuCloseAnimation(); 
        } 
    } 
 
    /**
     * 打開menu菜單窗口動畫
     */ 
    private void startMenuOpenAnimation() 
    { 
        // 由於打開菜單高度不一至所以根據菜單的高度來設置打開菜單時間  
        menuOpenMillis = (mitems.size() * 100) + 100; 
        if (menuOpenMillis > 500) 
        { 
            menuOpenMillis = 500; 
        } 
        myMenuOpen = new TranslateAnimation(0f, 0f, -(listview.getHeight() + 1), 0f); 
        myMenuOpen.setDuration(menuOpenMillis); 
        listview.startAnimation(myMenuOpen); 
    } 
 
    /**
     * 關閉menu菜單窗口動畫
     */ 
    private void startMenuCloseAnimation() 
    { 
        myMenuClose = new TranslateAnimation(0f, 0f, 0f, -(listview.getHeight() + 1)); 
        myMenuClose.setDuration(menuCloseMillis); 
        listview.startAnimation(myMenuClose); 
        myHandler.sendEmptyMessageDelayed(MENU_CLOSE_ANIM, menuCloseMillis); 
    } 
 
    public class ItemTextListAdapter extends SimpleAdapter 
    { 
 
        public ItemTextListAdapter(Context context) 
        { 
            super(context, null, 0, null, null); 
        } 
 
        @Override 
        public int getCount() 
        { 
            return mitems.size(); 
        } 
 
        @Override 
        public View getView(final int position, View convertView, ViewGroup parent) 
        { 
            ItemHolder holder; 
            if (convertView == null || convertView.getTag() == null || !(convertView.getTag() instanceof ItemHolder)) 
            { 
                convertView = LayoutInflater.from(mContext).inflate(R.layout.hotalk_menu_item_view, null, true); 
                holder = new ItemHolder(); 
                holder.menuName = (TextView) convertView.findViewById(R.id.textview); 
            } 
            else 
            { 
                holder = (ItemHolder) convertView.getTag(R.layout.hotalk_menu_item_view); 
            } 
            convertView.setTag(holder); 
            convertView.setTag(R.layout.hotalk_menu_item_view, holder); 
            MenuItem item = mitems.get(position); 
            holder.menuName.setText(item.MenuValue); 
            holder.menuName.setTextSize(FusionField.SET_TYPE_TEXT_SIZE); 
            convertView.setTag(item.MenuKey); 
            return convertView; 
        } 
    } 
 
    public static class ItemHolder 
    { 
        TextView menuName; 
    } 
 
    public class MenuItem implements Comparable 
    { 
        int MenuKey; 
 
        String MenuValue; 
 
        public MenuItem(int key, String value) 
        { 
            MenuKey = key; 
            MenuValue = value; 
        } 
 
        @Override 
        public int compareTo(Object o) 
        { 
            // TODO Auto-generated method stub  
            return this.MenuKey – ((MenuItem) o).MenuKey; 
        } 
    } 

package com.jindegege.demo;

import java.util.ArrayList;
import java.util.Collections;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Paint;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.TextView;

 

public class HotalkMenuView extends View
{
    /**
     * 發送短信的模式 hotalk或者短信
     */
    public final static int MENU_SEND_MSG_FORMULAR = 0;

    /**
     * 查看聯系人
     */
    public final static int MENU_VIEW_CONTACT = 1;

    /**
     * 添加聯系人
     */
    public final static int MENU_ADD_CONTACT = 2;

    /**
     * 群成員管理
     */
    public final static int MENU_MEMBER_MANAGER = 3;

    /**
     * 批量收藏
     */
    public final static int MENU_ADD_TO_FAVORITES = 4;

    /**
     * 批量刪除
     */
    public final static int MENU_DELETE_MULTI_MSG = 5;

 

    /**
     * 上下文
     */
    private Context mContext;

    /**
     * PopupWindow
     */
    private PopupWindow popWindow;

    /**
     * 顯示View
     */
    private View popview;

    /**
     * listview
     */
    public ListView listview;

    /**
     * 填充數據集
     */
    public ArrayList<MenuItem> mitems = null;

    /**
     * 設置顯示位置
     */
    RelativeLayout layout;

    /**
     * 橫屏菜單距離最大高度
     */
    private int bottomLenght_h = 77;

    /**
     * 豎屏菜單距離最大高度
     */
    private int bottomLenght_v = 173;

    /**
     * 屏幕密度
     */
    private Display display;

    /**
     * 畫板用於測字符寬度
     */
    private Paint paint = null;

    /**
     * 菜單中最在的字符寬度
     */
    private float maxWeith = 0;

    /**
     * 顯示靠左邊菜單的左邊距
     */
    private int rightMenuLeft = 45;

    /**
     * 顯示靠左邊菜單的最大右邊距
     */
    private int maxRightWeith = 44;

    /**
     * 顯示靠左邊菜單的最小右邊距
     */
    private int minRightWeith = 140;

    /**
     * 菜單的最小左邊距
     */
    private int maxLeftWeith = 88;

    /**
     * 菜單的最小左邊距
     */
    private int minLeftWeith = 188;

    /**
     * 橫屏菜單最小左邊距
     */
    private int maxLeftWeith_h = 282;

    /**
     * 橫屏菜單最小左邊距
     */
    private int minLeftWeith_h = 371;

    /**
     * 菜單的背景和文字兩邊占間距
     */
    private int contentSpaceWeith = 38;

    /**
     * 打開Menu動畫
     */
    private TranslateAnimation myMenuOpen;

    /**
     * 關閉Menu動畫
     */
    private TranslateAnimation myMenuClose;

    /**
     * 打開Menu動畫所用時間
     */
    private int menuOpenMillis = 500;

    /**
     * 關閉Menu動畫 所用時間
     */
    private int menuCloseMillis = 400;

    /**
     * 彈出窗口播放Menu的動畫
     */
    private final int MENU_OPEN_ANIM = 1;

    /**
     * 關閉Menu動畫 後關閉窗口
     */
    private final int MENU_CLOSE_ANIM = 2;

    /**
     * 當前窗口handler
     */
    private MyHandler myHandler = new MyHandler();

    /**
     * 正在進行關閉Menu操作
     */
    private boolean isDismissing = false;

    class MyHandler extends Handler
    {
        @Override
        public void handleMessage(Message msg)
        {
            if (msg == null)
            {
                return;
            }
            super.handleMessage(msg);
            switch (msg.what)
            {
                case MENU_OPEN_ANIM:
                    startMenuOpenAnimation();
                    break;
                case MENU_CLOSE_ANIM:
                 if(popWindow!=null){
                    popWindow.dismiss();
                 }
                    isDismissing = false;
                    break;
            }
        }
    }

    public HotalkMenuView(Context context)
    {
        super(context);
        mContext = context;
        mitems = new ArrayList<MenuItem>();
        LayoutInflater layoutInflater = (LayoutInflater) (mContext).getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
        // 獲取自定義佈局文件的視圖
        popview = layoutInflater.inflate(R.layout.hotalk_menu_view, null);
        listview = (ListView) popview.findViewById(R.id.hotalk_menu_listview);
        layout = (RelativeLayout) popview.findViewById(R.id.hotalk_menu_view_layout);
        adapter = new ItemTextListAdapter(mContext);
        popWindow = new PopupWindow(popview, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);//以PopupWindow彈出
        display = ((WindowManager) mContext.getSystemService(mContext.WINDOW_SERVICE)).getDefaultDisplay();
        initValue();
        layout.setOnClickListener(onclick);
        listview.setFocusable(false);
        listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        listview.setAdapter(adapter);
        listview.setFocusableInTouchMode(true);
        listview.setMinimumHeight(200);
        listview.setOnKeyListener(new OnKeyListener()
        {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event)
            {
                // 正執行關閉Menu菜單操作將不重復操作
                if (!isDismissing)
                {
                    isDismissing = true;
                    if ((keyCode == KeyEvent.KEYCODE_MENU) && (popWindow.isShowing()))
                    {
                        close();
                    }
                    else if (((keyCode == KeyEvent.KEYCODE_BACK) && (popWindow.isShowing())))
                    {
                        close();
                    }
                }

                return false;
            }
        });
    }

    /**
     * 初始設置Menu位置參數
     */
    private void initValue()
    {
        paint = new Paint();
        rightMenuLeft = (int) (rightMenuLeft * FusionField.currentDensity);
        maxLeftWeith = (int) (maxLeftWeith * FusionField.currentDensity);
        minLeftWeith = (int) (minLeftWeith * FusionField.currentDensity);
        maxRightWeith = (int) (maxRightWeith * FusionField.currentDensity);
        minRightWeith = (int) (minRightWeith * FusionField.currentDensity);
        bottomLenght_h = (int) (bottomLenght_h * FusionField.currentDensity);
        bottomLenght_v = (int) (bottomLenght_v * FusionField.currentDensity);
        contentSpaceWeith = (int) (contentSpaceWeith * FusionField.currentDensity);
        maxLeftWeith_h = (int) (maxLeftWeith_h * FusionField.currentDensity);
        minLeftWeith_h = (int) (minLeftWeith_h * FusionField.currentDensity);
    }

    /**
     * 添加菜單項
     *
     * @param key
     * @param value
     */
    public void add(int key, String value)
    {
        remove(key);
        MenuItem item = new MenuItem(key, value);
        mitems.add(item);
        adapter.notifyDataSetChanged();

    }

    /**
     * 添加 菜單項
     *
     * @param position 位置(必須是按0~n)添加
     * @param key
     * @param value
     */
    public void add(int position, int key, String value)
    {
        MenuItem item = new MenuItem(key, value);
        if (position == mitems.size())
        {
            mitems.add(position, item);

            adapter.notifyDataSetChanged();
        }
    }

    /**
     * 獲取文本最大長度
     */
    private void getContextMaxLength()
    {
        adapter.notifyDataSetChanged();
        if (mitems != null && mitems.size() > 0)
        {
            maxWeith = 0;
            if (Build.VERSION.SDK_INT >= 14)
            {
                // android 4.0手機當前字體大小自適
                TextView tv = new TextView(mContext);
                tv.setTextSize(FusionField.SET_TYPE_TEXT_SIZE);
                float size = tv.getTextSize() / FusionField.SET_TYPE_TEXT_SIZE;
                paint.setTextSize((int) ((size * 12) * FusionField.currentDensity));
            }
            else
            {
                paint.setTextSize((int) ((FusionField.SET_TYPE_TEXT_SIZE + 1) * FusionField.currentDensity));
            }

            for (int i = 0; i < mitems.size(); i++)
            {
                if (paint.measureText(mitems.get(i).MenuValue) > maxWeith)
                {
                    maxWeith = paint.measureText(mitems.get(i).MenuValue);
                }
            }
        }
    }

    /**
     * 更新菜單項按位置更新
     *
     * @param position
     * @param key
     * @param value
     */
    public void updateItem(int position, int key, String value)
    {
        if (mitems.size() > position)
        {
            remover(position);
            MenuItem item = new MenuItem(key, value);
            mitems.add(position, item);
        }
    }

    /**
     * 刪除菜單項
     *
     * @param position
     */
    public void remover(int position)
    {
        if (mitems.size() > position)
        {
            mitems.remove(position);
        }
    }

    /**
     * 刪除菜單項 add by shaxinajun
     *
     * @param position
     */
    public void remove(int key)
    {
        MenuItem item = null;
        for (int i = 0; i < mitems.size(); i++)
        {
            item = mitems.get(i);
            if (item.MenuKey == key)
            {
                mitems.remove(i);
                break;
            }
        }
    }

    /**
     * 清空菜單項
     */
    public void clear()
    {
        mitems.clear();
        maxWeith = 0;
    }

    ItemTextListAdapter adapter;

    /**
     * 設置Menu顯示位置,不可以自適應屏幕 密度 方法表述
     *
     * @param left
     * @param top
     * @param right
     * @param bottom void
     */
    public void setMenuPosition(int left, int top, int right, int bottom)
    {
        layout.setPadding(left, (int) (46 * FusionField.currentDensity), right, bottom);
    }

    /**
     * 單擊事件
     */
    private OnClickListener onclick = new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            switch (v.getId())
            {
            // 點擊空白外讓其消失
                case R.id.hotalk_menu_view_layout:
                    close();
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * 重新設置菜單項
     *
     * @param list
     */
    public void setItems(ArrayList<String> items)
    {
        mitems.clear();
        if (items != null && items.size() > 0)
        {
            for (int i = 0; i < items.size(); i++)
            {
                MenuItem item = new MenuItem(0, items.get(i));
                mitems.add(item);
            }
        }
    }

    public void setPositionShow()
    {
        try
        {
            if (popWindow != null && popview != null)
            {
                if (popWindow.isShowing())
                {
                    startMenuCloseAnimation();
                }
                else
                {
                    getContextMaxLength();
                   int right = (int) ((320 * FusionField.currentDensity) – (maxWeith + rightMenuLeft + contentSpaceWeith));
                
                    if (right < maxRightWeith)
                    {
                        right = maxRightWeith;
                    }
                    else if (right > minRightWeith)
                    {
                        right = minRightWeith;
                    }
                    //setMenuPosition(rightMenuLeft, 10, right, bottomLenght_v);
                    setMenuPosition(rightMenuLeft, 0, 0, bottomLenght_v);
                    Collections.sort(mitems);
                    // 規定彈窗的位置
                    popWindow.setFocusable(true);
                    popWindow.update();
                    popWindow.showAtLocation(popview, Gravity.FILL, 0, 0);
                    myHandler.sendEmptyMessage(MENU_OPEN_ANIM);
                }
            }
        }
        catch (Exception e)
        {
            Log.i("HotalkMenuView", "e:" + e.toString());
            close();
        }
    }

    /**
     * 顯示
     */
    public void show()
    {
        try
        {
            if (popWindow != null && popview != null)
            {
                if (popWindow.isShowing())
                {
                    startMenuCloseAnimation();
                }
                else
                {
                    if (mitems != null && mitems.size() > 0)
                    {
                        int orientation = display.getOrientation();
                        if (orientation == 0)
                        {// 豎屏
                            if (FusionField.currentActivity != null
                                    && FusionField.currentActivity.getCurrentFocus() != null
                                    && FusionField.currentActivity.getCurrentFocus().getWindowToken() != null)
                            {
                                ((InputMethodManager) FusionField.currentActivity
                                        .getSystemService(FusionField.currentActivity.INPUT_METHOD_SERVICE))
                                        .hideSoftInputFromWindow(FusionField.currentActivity.getCurrentFocus()
                                                .getWindowToken(), 0);
                            }
                            getContextMaxLength();
                            int left = (int) ((320 * FusionField.currentDensity) – (maxWeith + contentSpaceWeith));
                            if (left < maxLeftWeith)
                            {
                                left = maxLeftWeith;
                            }
                            else if (left > minLeftWeith)
                            {
                                left = minLeftWeith;
                            }
                            setMenuPosition(left, 0, 0, bottomLenght_v);

                        }
                        else
                        // 橫屏
                        {
                            getContextMaxLength();
                            int left = (int) ((533 * FusionField.currentDensity) – (maxWeith + contentSpaceWeith));
                            Log.i("jindegege", "left:" + left + " rightMenuLeft:"
                                    + (480 * FusionField.currentDensity));
                            if (left < maxLeftWeith_h)
                            {
                                left = maxLeftWeith_h;
                            }
                            else if (left > minLeftWeith_h)
                            {
                                left = minLeftWeith_h;
                            }
                            setMenuPosition(left, 0, 0, bottomLenght_h);
                        }
                        Collections.sort(mitems);
                        // 規定彈窗的位置
                        popWindow.setFocusable(true);
                        popWindow.update();
                        popWindow.showAtLocation(listview, Gravity.FILL, 0, (int) (46 * FusionField.currentDensity));
                        myHandler.sendEmptyMessage(MENU_OPEN_ANIM);

                    }
                }
            }
        }
        catch (Exception e)
        {
            Log.i("HotalkMenuView", "show() e:" + e.toString());
            close();
        }
    }

    /**
     * 判讀是否顯示
     *
     * @return boolean
     */
    public boolean getIsShow()
    {
        return popWindow.isShowing();
    }

    /**
     * 關閉
     */
    public void close()
    {
        if (popWindow != null && popWindow.isShowing())
        {
            startMenuCloseAnimation();
        }
    }

    /**
     * 打開menu菜單窗口動畫
     */
    private void startMenuOpenAnimation()
    {
        // 由於打開菜單高度不一至所以根據菜單的高度來設置打開菜單時間
        menuOpenMillis = (mitems.size() * 100) + 100;
        if (menuOpenMillis > 500)
        {
            menuOpenMillis = 500;
        }
        myMenuOpen = new TranslateAnimation(0f, 0f, -(listview.getHeight() + 1), 0f);
        myMenuOpen.setDuration(menuOpenMillis);
        listview.startAnimation(myMenuOpen);
    }

    /**
     * 關閉menu菜單窗口動畫
     */
    private void startMenuCloseAnimation()
    {
        myMenuClose = new TranslateAnimation(0f, 0f, 0f, -(listview.getHeight() + 1));
        myMenuClose.setDuration(menuCloseMillis);
        listview.startAnimation(myMenuClose);
        myHandler.sendEmptyMessageDelayed(MENU_CLOSE_ANIM, menuCloseMillis);
    }

    public class ItemTextListAdapter extends SimpleAdapter
    {

        public ItemTextListAdapter(Context context)
        {
            super(context, null, 0, null, null);
        }

        @Override
        public int getCount()
        {
            return mitems.size();
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent)
        {
            ItemHolder holder;
            if (convertView == null || convertView.getTag() == null || !(convertView.getTag() instanceof ItemHolder))
            {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.hotalk_menu_item_view, null, true);
                holder = new ItemHolder();
                holder.menuName = (TextView) convertView.findViewById(R.id.textview);
            }
            else
            {
                holder = (ItemHolder) convertView.getTag(R.layout.hotalk_menu_item_view);
            }
            convertView.setTag(holder);
            convertView.setTag(R.layout.hotalk_menu_item_view, holder);
            MenuItem item = mitems.get(position);
            holder.menuName.setText(item.MenuValue);
            holder.menuName.setTextSize(FusionField.SET_TYPE_TEXT_SIZE);
            convertView.setTag(item.MenuKey);
            return convertView;
        }
    }

    public static class ItemHolder
    {
        TextView menuName;
    }

    public class MenuItem implements Comparable
    {
        int MenuKey;

        String MenuValue;

        public MenuItem(int key, String value)
        {
            MenuKey = key;
            MenuValue = value;
        }

        @Override
        public int compareTo(Object o)
        {
            // TODO Auto-generated method stub
            return this.MenuKey – ((MenuItem) o).MenuKey;
        }
    }
}
在這個工具類中,構造方法是關鍵,在這裡新建瞭一個adapter對象有用填充listview中的數據,

 adapter = new ItemTextListAdapter(mContext);

構造瞭一個popupWindow對象,傳入的三個對象依次表示,popview這個listview對象,彈出的寬、高都是

[java]
FILL_PARENT, 
FILL_PARENT,[java]
popWindow = new PopupWindow(popview, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);//以PopupWindow彈出 
 popWindow = new PopupWindow(popview, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);//以PopupWindow彈出[java]
5、下面就給出activity類 
5、下面就給出activity類[java]
<pre name="code" class="java">package com.jindegege.demo; 
import android.app.Activity; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
 
public class MenudemoActivity extends Activity { 
      /**
     * 系統菜單定制控件
     */ 
    public HotalkMenuView menuListView = null; 
    /**
     * 原來系統menu菜單全部移到這裡操作
     */ 
  
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
       
         
         
    } 
    /**
     * 系統菜單初始化 void
     */ 
    private void initSysMenu() 
    { 
        if (menuListView == null) 
        { 
            menuListView = new HotalkMenuView(this); 
        } 
        menuListView.listview.setOnItemClickListener(listClickListener); 
        menuListView.clear(); 
        // 添加按位置添加  
        menuListView.add(HotalkMenuView.MENU_SEND_MSG_FORMULAR, getString(R.string.currFormularStr)); 
        menuListView.add(HotalkMenuView.MENU_VIEW_CONTACT, getString(R.string.chat_search_card)); 
        menuListView.add(HotalkMenuView.MENU_ADD_CONTACT, getString(R.string.chat_menu_addtocontact)); 
        menuListView.add(HotalkMenuView.MENU_DELETE_MULTI_MSG, getString(R.string.chat_menu_delete_msg)); 
        menuListView.add(HotalkMenuView.MENU_ADD_TO_FAVORITES, getString(R.string.multi_favorites)); 
     } 
 
    protected void switchSysMenuShow() 
    { 
        // 初始化系統菜單   
        initSysMenu(); 
        if (!menuListView.getIsShow()) 
        { 
     
            menuListView.show(); 
        } 
        else 
        { 
            menuListView.close(); 
        } 
    } 
 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) 
    { 
        menu.add("menu");// 必須創建一項  
        return super.onCreateOptionsMenu(menu); 
    } 
 
    @Override 
    public boolean onMenuOpened(int featureId, Menu menu){ 
   
        switchSysMenuShow(); 
     
        return false;// 返回為true 則顯示系統menu  
     
    } 
    /**
     * 菜單點擊事件處理
     */ 
    OnItemClickListener listClickListener = new OnItemClickListener() 
    { 
        @Override 
        public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) 
        { 
            // 獲取key唯一標識  
            int key = Integer.parseInt(view.getTag().toString()); 
 
            // 跳轉  
            switch (key) 
            { 
                case HotalkMenuView.MENU_SEND_MSG_FORMULAR: 
                    //editFormular();  
                    break; 
                case HotalkMenuView.MENU_VIEW_CONTACT: 
                    break; 
                case HotalkMenuView.MENU_ADD_CONTACT: 
                    break; 
                case HotalkMenuView.MENU_DELETE_MULTI_MSG: 
                    break; 
                case HotalkMenuView.MENU_ADD_TO_FAVORITES: 
                    break;          
                default: 
                    break; 
            } 
            // 關閉  
            menuListView.close(); 
        } 
 
    }; 
     
 

<pre name="code" class="java">package com.jindegege.demo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

public class MenudemoActivity extends Activity {
   /**
     * 系統菜單定制控件
     */
    public HotalkMenuView menuListView = null;
    /**
     * 原來系統menu菜單全部移到這裡操作
     */
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
     
       
       
    }
    /**
     * 系統菜單初始化 void
     */
    private void initSysMenu()
    {
        if (menuListView == null)
        {
            menuListView = new HotalkMenuView(this);
        }
        menuListView.listview.setOnItemClickListener(listClickListener);
        menuListView.clear();
        // 添加按位置添加
        menuListView.add(HotalkMenuView.MENU_SEND_MSG_FORMULAR, getString(R.string.currFormularStr));
        menuListView.add(HotalkMenuView.MENU_VIEW_CONTACT, getString(R.string.chat_search_card));
        menuListView.add(HotalkMenuView.MENU_ADD_CONTACT, getString(R.string.chat_menu_addtocontact));
        menuListView.add(HotalkMenuView.MENU_DELETE_MULTI_MSG, getString(R.string.chat_menu_delete_msg));
        menuListView.add(HotalkMenuView.MENU_ADD_TO_FAVORITES, getString(R.string.multi_favorites));
     }

    protected void switchSysMenuShow()
    {
        // 初始化系統菜單
        initSysMenu();
        if (!menuListView.getIsShow())
        {
   
            menuListView.show();
        }
        else
        {
            menuListView.close();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        menu.add("menu");// 必須創建一項
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu){
 
        switchSysMenuShow();
   
        return false;// 返回為true 則顯示系統menu
   
    }
    /**
     * 菜單點擊事件處理
     */
    OnItemClickListener listClickListener = new OnItemClickListener()
    {
        @Override
        public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3)
        {
            // 獲取key唯一標識
            int key = Integer.parseInt(view.getTag().toString());

            // 跳轉
            switch (key)
            {
                case HotalkMenuView.MENU_SEND_MSG_FORMULAR:
                    //editFormular();
                    break;
                case HotalkMenuView.MENU_VIEW_CONTACT:
                    break;
                case HotalkMenuView.MENU_ADD_CONTACT:
                    break;
                case HotalkMenuView.MENU_DELETE_MULTI_MSG:
                    break;
                case HotalkMenuView.MENU_ADD_TO_FAVORITES:
                    break;        
                default:
                    break;
            }
            // 關閉
            menuListView.close();
        }

    };
 

}
要實現項目中的效果,還必須有其他許多東西,在這裡無法演示,大傢可以自行去研究,然後補充設計更好的效果

[java]
給出demo的下載地址供大傢研究 
給出demo的下載地址供大傢研究[java]
<a href="http://download.csdn.net/detail/jindegegesun/4339121">http://download.csdn.net/detail/jindegegesun/4339121</a> 
<a href="http://download.csdn.net/detail/jindegegesun/4339121">http://download.csdn.net/detail/jindegegesun/4339121</a>

 

 

摘自 jindegegesun的專欄

發佈留言