下面是一個彈出帶ListView和TextView的PopupWindow實例:android
import android.app.Activity; import android.content.Context; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.AdapterView; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.TextView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; /** * Created by SRain on 2015/10/15. * <p/> * 彈出框 */ public class PopupWindowUtils implements View.OnClickListener { private PopupWindow popupWindow; private Context context; private View view; private TextView tvClose; private JSONArray jsonArray; private BasicPopuListAdapter adapter; //ListView的適配器 public PopuWindowUtils(Context context, View view, JSONArray jsonArray, int index) { this.context = context; this.view = view; this.jsonArray = jsonArray; initPopuWindow(index); } /** * 彈出popupwindow * * @param index 彈出框樣式標識 */ private void initPopuWindow(final int index) { View contentView = LayoutInflater.from(context).inflate(R.layout.layout_popupwindow, null); ListView listView = (ListView) contentView.findViewById(R.id.lv_files); tvClose = (TextView) contentView.findViewById(R.id.tvClose); tvClose.setVisibility(View.VISIBLE); tvClose.setOnClickListener(this); /* * 建立PopupWindow實例 * getScreenWidth(), (int) (getScreenWidth() * 0.6))分別是寬度和高度 */ if (popupWindow == null) { popupWindow = new PopupWindow(contentView, getScreenWidth(), (int) (getScreenWidth() * 0.6)); } // 自定義view添加觸摸事件 contentView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); return true; } // 這裏若是返回true的話,touch事件將被攔截 // 攔截後 PopupWindow的onTouchEvent不被調用,這樣點擊外部區域沒法dismiss return false; } }); switch (index) { case 1: adapter = new RoutePupuAdapter(context, jsonArray); break; } listView.setAdapter(adapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { try { adapter.setSelectedPosition(position); // 更新列表框 adapter.notifyDataSetInvalidated(); JSONObject object = jsonArray.getJSONObject(position); clickFunction(index, object); } catch (JSONException e) { Log.e("onItemClick", e.toString()); } } }); popupWindow.setAnimationStyle(R.style.PopupAnimation); popupWindow.setFocusable(true); /* * 彈出框位置 */ popupWindow.showAsDropDown(view, 0, -110); //popupWindow.showAtLocation(MainActivity.this.findViewById(R.id.main), Gravity.BOTTOM|Gravi //ty.CENTER_HORIZONTAL, 0, 0); //設置layout在PopupWindow中顯示的位置,從底部彈出 } /** * 根據屏幕寬度設置高度值 */ private int getScreenWidth() { //獲取屏幕寬度 DisplayMetrics dm = new DisplayMetrics(); double densityDpi = dm.density; //獲取屏幕信息 ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm); int screenWidth = dm.widthPixels; return screenWidth; } public void clickFunction(int index, JSONObject json) { switch (index) { case 1: ((LocationMapActivity) context).initRoadLines(json); break; } } /** * 銷燬PopupWindow */ public boolean dismissPopu() { if (popupWindow != null && popupWindow.isShowing()) { popupWindow.dismiss(); return true; } return false; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tvClose: dismissPopu(); break; } } }
//這是BasicPopuListAdapter代碼,本身的listview中adapter繼承它就能夠了: import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import org.json.JSONArray; import org.json.JSONObject; /** * Created by SRain on 2015/10/20. * <p/> * 普通listview適配器 */ public abstract class BasicPopuListAdapter extends BaseAdapter { protected Context context; protected JSONArray array; protected LayoutInflater mInflater; private int selectedPosition = -1; public BasicPopuListAdapter(Context context, JSONArray array) { this.context = context; this.array = array; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return array.length(); } @Override public Object getItem(int position) { JSONObject object = null; try { object = array.getJSONObject(position); } catch (Exception e) { } return object; } @Override public long getItemId(int position) { return position; } @Override public abstract View getView(int position, View convertView, ViewGroup parent); public abstract void setSelectedPosition(int position); public JSONArray getData(){ return this.array; } }
這是彈出框的佈局文件:json
<?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:background="@color/result_view" android:orientation="vertical"> <ListView android:id="@+id/lv_files" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/tvClose" android:layout_marginTop="2dp" android:visibility="gone" android:layout_width="match_parent" android:layout_height="45dp" android:background="@color/green" android:gravity="center" android:text="關閉" android:textColor="@color/white" /> </LinearLayout>
style中添加:app
<style name="PopupAnimation" mce_bogus="1" parent="android:Animation"> <item name="android:windowEnterAnimation">@anim/dialog_enter</item> <item name="android:windowExitAnimation">@anim/dialog_exit</item> </style>
drawable中添加dialog_enter.xml和dialog_exit.xml:ide
<!--dialog_enter--> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="500" android:fromYDelta="500" android:toYDelta="0" /> </set>
<!--dialog_exit--> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="500" android:fromYDelta="0" android:toYDelta="500" /> </set>
補充:
在用PopupWindow實現底部彈出菜單的時候要注意幾個問題:
1)若是彈出菜單中有EditText這種輸入控件,若是不給PopupWindow設置可獲取焦點的話,EditText是沒法獲取輸入的。
2)必定要設置 虛擬軟鍵盤隨須要更改屏幕顯示內容的大小,不然虛擬軟鍵盤會被底部彈出菜單遮擋。
3)若是設置了PopupWindow可獲取焦點的話,此時會遇到一個問題就是當PopupWindow中的控件好比EditText獲取焦點以後,點擊PopupWindow以外的控件是不會有響應的,若是用setBackgroundDrawable(new BitmapDrawable())進行設置的話,則不會出現這種狀況。
//設置能夠獲取焦點,不然彈出菜單中的EditText是沒法獲取輸入的
popWindow.setFocusable(true);
//這句是爲了防止彈出菜單獲取焦點以後,點擊activity的其餘組件沒有響應
popWindow.setBackgroundDrawable(new BitmapDrawable());
//防止虛擬軟鍵盤被彈出菜單遮住
popWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
//在底部顯示
popWindow.showAtLocation(this,Gravity.BOTTOM, 0, 0);佈局
4)popupWindow.setBackgroundDrawable(new BitmapDrawable()); // 須要設置一下此參數,點擊外邊可消失, 若是不設置PopupWindow的背景,不管是點擊外部區域仍是Back鍵都沒法dismiss彈框this
popupWindow.setOutsideTouchable(true); // 設置popwindow若是點擊外面區域,便關閉。
popupWindow.setFocusable(true); // 設置此參數得到焦點,不然沒法點擊
popupWindow.update();spa
5)PopupWindow和AlertDialog的區別線程
Android的對話框有兩種:PopupWindow和AlertDialog。它們的不一樣點在於:code
PopupWindow的位置按照有無偏移分,能夠分爲偏移和無偏移兩種;按照參照物的不一樣,能夠分爲相對於某個控件(Anchor錨)和相對於父控件。具體以下xml