天天看點

封裝的一個android底部操作彈出窗

首先看效果

封裝的一個android底部操作彈出窗

調用方式也非常的簡單如下:

//操作需要用到的圖檔icon
        final int itemIconIds[] = new int[] { R.drawable.p_trends_comment,
                R.drawable.p_trends_forward, R.drawable.p_trends_share,
                R.drawable.p_trends_delete };
        
        final String itemDescs[] = new String[] { "評  論", "轉  發", "共  享",
                "删  除" };
        
        //獲得螢幕的高度,設定ListView的最大高度,動态設定ListView的高度
        WindowManager windowManager = this.getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        int screenHeight = display.getHeight();
        
        showBtn = (Button) this.findViewById(R.id.show);
        
        new PathPopupWindowDialog(this, screenHeight, showBtn).create(itemIconIds,
                itemDescs,
                new ResponseListener());
           

PathPopupWindowDialog的參數說明:

構造函數中第一個參數“this”是Context,第二個"screenHeight"是螢幕的高度,本來是要根據内容的增加,來不斷調整dialog的高度的,暫時看來是不需要了,第三個參數"showBtn"是用來觸發此dialog的一個按鈕,其實是PopupWindow的showAtLocation需要的parentView

create方法中的參數分别是dialog中每一個item需要的圖示和對應的文字,以及單擊每一個條目需要觸發的事件,内容形式示例如下:

private class ResponseListener implements AdapterView.OnItemClickListener
    {
        @Override
        public void onItemClick(AdapterView<?> adapter, View view, int id,
                long position)
        {
            System.out.println(view + "----");
            @SuppressWarnings("unchecked")
            HashMap<String, Object> map = (HashMap<String, Object>) adapter.getItemAtPosition((int) position);
            Toast.makeText(Android_test_02Activity.this,
                    map.get("text").toString(),
                    1000).show();
        }
    }
           

其中PathPopupWindowDialog的源碼如下:

package com.king.demo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.SimpleAdapter;

/**
 * path dialog元件 <br/>
 * <br/>
 * <b>示例:<br/>
 * new PathPopupWindowDialog(Context context, int screenHeight, View showBtn)<br/>
 *     .create(int itemIconIds[],String itemDescs[],
 * AdapterView.OnItemClickListener listener);<br/>
 * <br/>
 * 參數說明:<br/>
 * context ---- 一般是activity<br/>
 * screenHeight ---- 螢幕高度<br/>
 * showBtn ---- 用來PopupWindow展示,例如Button,點選此button會顯示dialog<br/>
 * itemIconIds ---- ListView中每一個item的圖示<br/>
 * itemDescs ---- ListView中每一個item的圖示對應的說明<br/>
 * listener ---- ListView中每一個item需要響應的操作,需要使用者自己實作。<br/>
 * 關于ListView中的值是通過SimpleAdapter設定的,其中SimpleAdapter接收的List<HashMap<String,
 * Object>><br/>
 * map中存放的key是圖示是"icon"[ITEM_ICON]和文本是"text"[ITEM_TEXT],使用者在實作listener的時候可能需要用到
 * </b>
 * 
 * @author kingzhang
 * 
 */
public class PathPopupWindowDialog
{
    
    public static final String ITEM_ICON = "icon";
    
    public static final String ITEM_TEXT = "text";
    
    /**
     * popupWindow
     */
    private PopupWindow popupWindow;
    
    /**
     * 确定dialog需要的context
     */
    private Context context;
    
    /**
     * 手機螢幕的高度
     */
    private int screenHeight;
    
    /**
     * 确定觸發該dialog的view元件,也是建立popupwindow必須的參數
     */
    private View parentView;
    
    public PathPopupWindowDialog(Context context, int screenHeight,
            View parentView)
    {
        this.context = context;
        this.screenHeight = screenHeight;
        this.parentView = parentView;
    }
    
    /**
     * 建立PopupWindow
     * 
     * @param itemIconIds
     *            ListView中的圖示
     * @param itemDescs
     *            ListView中圖示對應的描述
     * @param responseListener
     *            響應listview中的item click listener 事件
     */
    public void create(int itemIconIds[], String itemDescs[],
            AdapterView.OnItemClickListener responseListener)
    {
        LayoutInflater inflater = LayoutInflater.from(context);
        View popupView = inflater.inflate(R.layout.p_trends_option_popup, null);
        //popupView.se
        
        //從popu.xml中獲得其中的元件
        ListView listView = (ListView) popupView.findViewById(R.id.path_popupwindow_listview);
        
        //獲得popup中最外層的layout
        //LinearLayout linearLayout = (LinearLayout) popupView.findViewById(R.id.p_dynamic_popup_layout);
        
        //設定ListView中的參數屬性
        this.setListViewParamters(listView,
                itemIconIds,
                itemDescs,
                responseListener);
        
        //獲得螢幕的高度,設定ListView的最大高度,動态設定ListView的高度
        //this.setListViewHeightBasedOnChildren(listView, screenHeight);
        
        //生成PopupWindow對象
        popupWindow = new PopupWindow(popupView, LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT, true);
        
        //設定PopupWindow對象需要屬性參數
        popupWindow.setAnimationStyle(R.style.path_popwindow_anim_enterorout_window);
        popupWindow.setFocusable(true);
        popupWindow.setTouchable(true);
        
        //設定popupwindow以外的區域是否可以觸摸
        popupWindow.setOutsideTouchable(true);
        
        //顯示popupwindow
        parentView.setOnClickListener(new ShowPopupWindowListener());
        
        // 設定android傳回事件,用來隐藏popupwindow
        // 不給LinearLayout設定的原因是因為給其加上後,ListView不能獲得焦點
        this.setBackListener(listView);
        
    }
    
    /**
     * 設定ListView裡面的參數屬性
     * 
     * @param listView
     * @param itemIconIds
     *            ListView中的圖示
     * @param itemDescs
     *            ListView中圖示對應的描述
     * @param responseListener
     *            響應listview中的item click listener 事件
     */
    private void setListViewParamters(ListView listView, int itemIconIds[],
            String itemDescs[], AdapterView.OnItemClickListener responseListener)
    {
        
        // 給popu.xml中ListView設定值
        List<HashMap<String, Object>> itemList = new ArrayList<HashMap<String, Object>>();
        for (int i = 0; i < itemDescs.length; i++)
        {
            HashMap<String, Object> map = new HashMap<String, Object>();
            map.put(ITEM_ICON, itemIconIds[i]);
            map.put(ITEM_TEXT, itemDescs[i]);
            itemList.add(map);
        }
        
        SimpleAdapter simpleAdapter = new SimpleAdapter(context, itemList,
                R.layout.p_trends_option_popup_item, new String[] { "icon",
                        "text" }, new int[] { R.id.path_dynamic_popu_item_icon,
                        R.id.path_dynamic_popu_item_textView });
        listView.setFocusable(true);
        listView.requestFocus();
        listView.setAdapter(simpleAdapter);
        listView.setItemsCanFocus(true);
        listView.setDividerHeight(0);
        //設定ListView中的item點選事件
        listView.setOnItemClickListener(responseListener);
    }
    
    /**
     * 給parentView設定onclicklistener事件,用于顯示popupwindow
     * 
     * @author kingzhang
     * 
     */
    private class ShowPopupWindowListener implements View.OnClickListener
    {
        @Override
        public void onClick(View v)
        {
            popupWindow.showAtLocation(parentView, Gravity.BOTTOM, 0, 0);
            popupWindow.update();
        }
    }
    
    /**
     * 為PopupWindow中的最外層的布局設定onkeylistener事件 用來隐藏彈出的popupwindow
     * 
     * @param layout
     *            為PopupWindow中的最外層的布局
     * @param pw
     *            PopupWindow
     */
    private void setBackListener(View view)
    {
        view.setOnKeyListener(new View.OnKeyListener()
        {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event)
            {
                if (event.getAction() == KeyEvent.ACTION_DOWN
                        && keyCode == KeyEvent.KEYCODE_BACK)
                {
                    popupWindow.dismiss();
                }
                return false;
            }
        });
    }
    
    /**
     * 動态設定listview的高度
     * 
     * @param listView
     *            需要配置的ListView
     * @param screenHeight
     *            螢幕的高度
     * @param imageHeight
     *            imageHeight
     * @param viewHeight
     *            viewHeight
     */
    private void setListViewHeightBasedOnChildren(ListView listView,
            int screenHeigh)
    {
        //擷取ListView對應的Adapter
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
        {
            return;
        }
        int totalHeight = 0;
        for (int i = 0, len = listAdapter.getCount(); i < len; i++)
        {
            //listAdapter.getCount()傳回資料項的數目
            View listItem = listAdapter.getView(i, null, listView);
            
            //計算子項View 的寬高
            listItem.measure(0, 0);
            
            //統計所有子項的總高度
            totalHeight += listItem.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        
        //listView.getDividerHeight()擷取子項間分隔符占用的高度
        int listViewHeight = totalHeight
                + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        
        //如果總體高度大于螢幕高度,則用螢幕高度
        if (listViewHeight > screenHeight)
        {
            //此處的30是實驗所得出的結果
            params.height = screenHeight - 75;
        }
        //否則設定為計算出來的高度
        else
        {
            params.height = listViewHeight;
        }
        listView.setLayoutParams(params);
    }
}
           

布局檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- author king -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/p_dynamic_popup_layout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" 
    android:paddingTop="30dip">
	
    <!-- 顯示的高度跟這個LinearLayout的background的大小有關,以及和item裡面的backgroud有關 -->
    <!-- 用來顯示popupwindow中的清單項 -->
	
	<ImageView 
	    android:id="@+id/title_bg"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:src="@drawable/top"
	    android:scaleType="fitXY"/>
	
    <ListView
        android:id="@+id/path_popupwindow_listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingLeft="10dip"
        android:paddingRight="10dip" 
        android:background="@drawable/bg"
        android:cacheColorHint="#00000000"/>
    
    <ImageView
        android:id="@+id/bottom_bg"
        android:src="@drawable/bottom"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"/>
</LinearLayout>
           

<?xml version="1.0" encoding="utf-8"?>
<!-- author king -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="60dip"
    android:gravity="center"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/path_dynamic_popu_item_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:scaleType="centerInside"/>

    <TextView
        android:id="@+id/path_dynamic_popu_item_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginLeft="10dip"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:textSize="22sp"/>

</LinearLayout>
           

剩下的就是所用的圖檔背景如下:

封裝的一個android底部操作彈出窗
封裝的一個android底部操作彈出窗

用到的動畫效果的xml檔案如下:

enter window

<?xml version="1.0" encoding="utf-8"?>
<!-- author king -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator" >

    <translate
        android:duration="300"
        android:fromXDelta="0.0"
        android:fromYDelta="100%"
        android:toXDelta="0.0"
        android:toYDelta="0.0" />

</set>
           

out window

<?xml version="1.0" encoding="utf-8"?>
<!-- author king -->
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    android:interpolator="@android:anim/decelerate_interpolator">
    <translate
        android:duration="400"
        android:fromXDelta="0.0"
        android:fromYDelta="0.0"
        android:toXDelta="0.0"
        android:toYDelta="100%" />
</set>
           

style檔案外為:

<?xml version="1.0" encoding="utf-8"?>
<!-- author king -->
<resources>
    <style name="path_popwindow_anim_enterorout_window">
        <item name="android:windowEnterAnimation">@anim/p_trends_enter_window</item>
 		<!-- 指定顯示的動畫xml -->
        <item name="android:windowExitAnimation">@anim/p_trends_out_window</item>
 		<!-- 指定消失的動畫xml -->
    </style>
</resources>