先看最終效果圖:
原理一個將PopupWindow綁在一個TextView上,處理TextView點擊事件來彈框,右邊EditText實現輸入框,把EditText拿上來是由於在實習過程當中碰到很多細節問題。代碼:
main.xml //主頁面佈局
<RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/bgtitlebar" android:orientation="horizontal" android:padding="10dp" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" > <Button android:id="@+id/btn_header_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/btn_back" android:onClick="back" /> </LinearLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:text="@string/txt_search" android:textSize="18sp" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_divide_line_search" > <LinearLayout android:id="@+id/ll_search_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginTop="6dp" android:background="@drawable/bg_tv_search_category" >//由於一個控件只能有一張背景圖片,因此把「資訊」的另外一張背景圖片放在佈局上 <TextView android:id="@+id/search_category" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="3dp" android:layout_marginLeft="10dp" android:layout_marginTop="3dp" android:clickable="true" android:drawableRight="@drawable/bg_tv_search_pop"//這個屬性可將圖片放在控件的左側 android:text="@string/message" android:textColor="@color/blue" android:textSize="19sp" /> </LinearLayout> <LinearLayout android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginLeft="18dp" android:layout_toRightOf="@id/ll_search_txt" android:background="@drawable/bg_edt_search" android:layout_marginTop="9dp" > <EditText android:id="@+id/input_search_cagegory" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="5dp" android:background="@drawable/bg_edt_search" android:ems="10" android:drawableLeft="@drawable/bg_edt_search_icon android:hint="@string/input_search_txt" android:singleLine="true" /> </LinearLayout> </RelativeLayout>
popup_item.xml // PopupWindow 彈框內容,這裏只是簡單的TextView,涉及ListView的話要複雜些android
<?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:orientation="vertical" > <TextView android:id="@+id/search_picture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/picture" android:clickable="true" android:textSize="19sp" android:background="@drawable/bg_search_picture" /> <TextView android:id="@+id/search_video" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/video" android:clickable="true" android:textSize="19sp" android:background="@drawable/bg_search_video" /> <TextView android:id="@+id/search_message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/message" android:clickable="true" android:textSize="19sp" android:background="@drawable/bg_search_message" />
main.javasegmentfault
public class SearchActivity extends Activity { private PopupWindow window = null; private LayoutInflater inflater; private TextView txt_choosecategory; private TextView message; private TextView picture; private TextView video; private EditText edt_inputcagegory; private Button btn_header_back; private View view; private ListView listView; private String return_result; private String category_id; private String keyword; private SearchTask searchTask; private String category; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search); initHeader(); initBodyer(); } private boolean isInput() { if (isNullorSpace(edt_inputcagegory.getText().toString())) { return false; } return true; } private void initBodyer() { // final InputMethodManager imm = (InputMethodManager) //getSystemService(Context.INPUT_METHOD_SERVICE); txt_choosecategory = (TextView) findViewById(R.id.search_category); edt_inputcagegory = (EditText) findViewById(R.id.input_search_cagegory); edt_inputcagegory.setImeOptions(EditorInfo.IME_ACTION_SEARCH); //這行代碼的做用是把鍵盤右下角的「回車」鍵變成「搜索」鍵 txt_choosecategory.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (window != null) { //必定要先判斷是否爲空! if (window.isShowing()) {//isShowing()方法判斷當前是否已經彈窗,返回true則關閉PopupWindow window.dismiss(); window = null; } } else { showWindow();實際這裏是實現點擊一次彈出PopupWindow,再點擊一次關閉掉。 } } }); edt_inputcagegory .setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {//對鍵盤的搜索鍵監聽事件 if (actionId == EditorInfo.IME_ACTION_SEARCH) { if (isInput()) { search(); } else { //edt_inputcagegory.requestFocus(); //imm.showSoftInputFromInputMethod(edt_inputcagegory.getWindowToken(), 0); Toast.makeText(Main.this,"搜索內容不能爲空",Toast.LENGH_SHORT); } } return false; } }); } private void initHeader() { btn_header_back = (Button) findViewById(R.id.btn_header_back); btn_header_back.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { finish(); } }); } private boolean isNullorSpace(String str) { if (!"".equals(str.trim()) & (str != null)) return false; return true; } private void search() { //Handle search } private void showWindow() { inflater = (LayoutInflater) this .getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.item_search_category, null, false);//加載佈局 message = (TextView) view.findViewById(R.id.search_message); video = (TextView) view.findViewById(R.id.search_video); picture = (TextView) view.findViewById(R.id.search_picture); message.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { txt_choosecategory.setText(R.string.message); //錯誤代碼 window.dismiss(); window = null; } }); video.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { txt_choosecategory.setText(R.string.video);//錯誤代碼 window.dismiss(); window = null; } }); picture.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { txt_choosecategory.setText(R.string.picture);//錯誤代碼 window.dismiss(); window = null; } }); if (window == null) { window = new PopupWindow(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);//建立PopupWindow,第一個參數是將要展現的內容佈局,第2、三個是佈局大小(LayoutParamas.WRAP_CONTENT,LayoutParams.WRAP_CONTENT要求API >=11) } // int[] location = new int[2]; // window.showAsDropDown(txt_choosecategory); // window.showAtLocation(txt_choosecategory, Gravity.NO_GRAVITY, // location[0], location[1]); window.showAtLocation(txt_choosecategory, Gravity.NO_GRAVITY, 15, 160);//設置PopupWindow位置,第一個參數是指定PopupWindow依附的View,第二個是座標偏移量相對的起始點,Gravity.NO_GRAVITY= Gravity.LEFT | Gravity.TOP,最後兩個是偏移量,這個寫死了應該對屏幕適配不太好,並且很麻煩囧,暫時還沒找到方便的方法..歡迎大俠指路. }
須要注意的是:1.本人一開始用PopupWindow就曾經報錯: "Unable to add window -- token null is not valid",緣由在stackoverflow上找到:To avoid BadTokenException, you need to defer showing the popup until after all the lifecycle methods are called (-> activity window is displayed),簡而言之就是要在佈局所有加載完以後再去加載PopupWindow,顯示PopupWindow過早就會直接crash.
2.在Activity取出string資源文件值,textView.setText(R.string.XXX)是錯誤的寫法應g改成-->textView.setText(getString(R.string.xxx))或者getResources().getString(R.string.xxx),緣由:http://stackoverflow.com/questions/11536326/android-settext-r-string-values
(第一句一語道破天機,R.string.xxx僅僅是資源的ID,因此R.String.xxx獲得的是資源的編號)ide