1. 程式人生 > >利用PopupWindow做出仿IOS樣式的選擇器

利用PopupWindow做出仿IOS樣式的選擇器

專案中總會遇到這樣蛋疼的事情,android和ios同樣的功能,都用的同樣自帶的控制元件,做出來的效果就是:android的醜的不行,ios的挺好看。於是,老大一拍屁股,android的改成和ios樣式的一樣就好了。然後,android開發就苦比了,憑空多出若干工作量。好了,話不多說,直接上程式碼吧。下面是我專案遇到的一個仿ios選擇器的一個task,我邊貼程式碼邊說吧。

首先,看下這個選擇器的佈局檔案。

<?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="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/pop_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#ffffff"
        android:gravity="center_horizontal"
        android:orientation="vertical" >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/cancle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@null"
                android:text="@string/cancel"
                android:textColor="#999999" />

            <Button
                android:id="@+id/ok"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:background="@null"
                android:text="@string/ok"
                android:textColor="@color/TextLightGreen" />
        </RelativeLayout>

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="1dp"
            android:background="#999999" />

        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="120dp" >

            <RadioGroup
                android:id="@+id/until"
                android:layout_width="fill_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
            </RadioGroup>
        </ScrollView>
    </LinearLayout>

</RelativeLayout>

可以看出,這要就是由兩個按鈕還有一個RadioGroup組成,這個RadioGRoup上面套了一層ScrollView,這個ScrollView是固定高度的,不難看出,選擇器的選擇項就會由RadioGroup中的RadioButton去實現,RadioButton會在程式碼中動態的去載入。

下面看我我們自定義的PopupWindow的程式碼

public class UnitPopupWindow extends PopupWindow {

	private Button btn_cancle, btn_ok;
	private RadioGroup unit;
	private View mMenuView;
	private Context context;
	private RadioButton button;
	private ColorStateList csl;

	private boolean statusFlag = true;

	@SuppressLint("ResourceAsColor")
	public UnitPopupWindow(Activity context, OnClickListener itemsOnClick,
			OnCheckedChangeListener checkedChangeListener,
			ArrayList<String> dataList) {
		super(context);
		this.context = context;
		LayoutInflater inflater = (LayoutInflater) context
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mMenuView = inflater.inflate(R.layout.alert_dialogs, null);
		btn_cancle = (Button) mMenuView.findViewById(R.id.cancle);
		btn_ok = (Button) mMenuView.findViewById(R.id.ok);
		unit = (RadioGroup) mMenuView.findViewById(R.id.until);
		for (int i = 0; i < dataList.size(); i++) {
			button = new RadioButton(context);
			button.setButtonDrawable(null);
			button.setText(dataList.get(i));
			button.setId(i);
			button.setTextSize(25);
			button.setGravity(Gravity.CENTER);
			button.setHeight(90);

			button.setButtonDrawable(android.R.color.transparent);
			button.setPadding(0, 0, 0, 0);
			csl = context.getResources()
					.getColorStateList(R.drawable.utilcolor);
			button.setTextColor(csl);
			WindowManager wm1 = context.getWindowManager();
			button.setWidth(wm1.getDefaultDisplay().getWidth());
			button.setFocusable(true);

			unit.addView(button);
		}

		// 取消按鈕
		btn_cancle.setOnClickListener(itemsOnClick);
		// 設定按鈕監聽
		unit.setOnCheckedChangeListener(checkedChangeListener);

		btn_ok.setOnClickListener(itemsOnClick);
		// 設定SelectPicPopupWindow的View
		this.setContentView(mMenuView);
		// 設定SelectPicPopupWindow彈出窗體的寬
		this.setWidth(LayoutParams.MATCH_PARENT);
		// 設定SelectPicPopupWindow彈出窗體的高
		this.setHeight(LayoutParams.MATCH_PARENT);
		// 設定SelectPicPopupWindow彈出窗體可點選
		this.setFocusable(true);
		// 設定SelectPicPopupWindow彈出窗體動畫效果
		this.setAnimationStyle(R.style.AnimBottom);
		ColorDrawable dw = new ColorDrawable(0x00000000);
		// 設定SelectPicPopupWindow彈出窗體的背景
		this.setBackgroundDrawable(dw);
		// mMenuView新增OnTouchListener監聽判斷獲取觸屏位置如果在選擇框外面則銷燬彈出框
		mMenuView.setOnTouchListener(new OnTouchListener() {
			public boolean onTouch(View v, MotionEvent event) {
				int height = mMenuView.findViewById(R.id.pop_layout).getTop();
				int y = (int) event.getY();
				if (event.getAction() == MotionEvent.ACTION_UP) {
					if (y < height) {
						backgroundAlpha(1f);
						dismiss();
					}
				}
				return true;
			}
		});

	}


	public RadioGroup getUnit() {
		return unit;
	}

	public void setStatus(boolean status) {
		statusFlag = status;
		unit.postInvalidate();
	}

	private void backgroundAlpha(float bgAlpha) {
		WindowManager.LayoutParams lp = ((Activity) context).getWindow()
				.getAttributes();
		lp.alpha = bgAlpha; // 0.0-1.0
		((Activity) context).getWindow().setAttributes(lp);
	}

}

注意下里面的兩個監聽事件

OnClickListener:這是監聽確認和取消兩個button的監聽事件
OnCheckedChangeListener:這是監聽RadioButton選中狀態的監聽事件

順便貼下這個選擇器彈出時的動畫效果程式碼,上面程式碼中有設定過這樣的屬性,自己查詢。

 <style name="AnimBottom" parent="@android:style/Animation">
        <item name="android:windowEnterAnimation">@anim/push_bottom_in</item>
        <item name="android:windowExitAnimation">@anim/push_bottom_out</item>
  </style>

<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="100%p"
        android:toYDelta="0" />

    <alpha
        android:duration="100"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

</set>
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="200"
        android:fromYDelta="0"
        android:toYDelta="50%p" />

    <alpha
        android:duration="100"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />

</set>

最後就到我們的呼叫了。假設使用者在點選了一個button後會彈出一個單位切換的選擇器,可以在這個button的OnClick事件中做這樣的處理,直接上程式碼
          <pre name="code" class="java">           ArrayList mDataList = new ArrayList<String>();
                        //增加選擇內容的item
                        mDataList.add("km");
			mDataList.add("mile");
			menuWindow = new UnitPopupWindow(this, itemsOnClick,checkedChangeListener,mDataList); 
			menuWindow.setOnDismissListener(new OnDismissListener() {
				
				@Override
				public void onDismiss() {
					backgroundAlpha(1f);
				}
			});
            menuWindow.showAtLocation(this.findViewById(R.id.main), Gravity.RIGHT|Gravity.BOTTOM, 0, 0);
            backgroundAlpha(0.5f);

 
private OnClickListener  itemsOnClick = new OnClickListener(){  
        public void onClick(View v) {  
            menuWindow.dismiss();
            switch (v.getId()) {  
            case R.id.ok:  
                //點選確認的需要做的操作
                break; 
            default:  
                break;  
            }  
        }  
          
    };  

 private OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener() {
        
        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {    
            switch (checkedId) {
            case 0:
                mUtil = getString(R.string.km_txt);
                mUtilString = "KM";
                break;
            case 1:
                mUtil = getString(R.string.mile);
                mUtilString = "Mile";
                break;
            default:
                break;
            }
        }
    };
   以上就是仿ios選擇器的全部內容了,關於PopupWindow的一些基本api使用我這裡就不多說了,不是很難懂。