Android PopupWindow 實現自定義菜單彈窗效果

先看最終效果圖:
請輸入圖片描述
原理一個將PopupWindow綁在一個TextView上,處理TextView點擊事件來彈框,右邊EditText實現輸入框,把EditText拿上來是由於在實習過程當中碰到很多細節問題。代碼:
main.xml //主頁面佈局

java

<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

相關文章
相關標籤/搜索