1. 程式人生 > >Android基於開源專案的WheelView的時間、地址聯動選擇對話方塊

Android基於開源專案的WheelView的時間、地址聯動選擇對話方塊

        一晃離上次寫部落格差不多都過了半年了,現在工作中用到了一些實用的東西,想和大家分享一下。

現在實現的是一個基於開源專案WheelView的時間、地址聯動選擇的對話方塊,先看看效果圖,文章末尾有原始碼下載地址

選擇時間:


選擇地點:


因為專案中要實現如圖上的效果,無奈WheelView的預設沒有,所以就修改了一點其中的程式碼和風格,就實現了這種效果。

步驟如下:

1、要實現選中字型變大,所以就得得到顯示文字的TextView的引用,所以這裡在原始碼“AbstractWheelTextAdapter”中添加了記錄顯示文字的TextView的集合、字型的最小顯示、最大顯示值以及記錄當前選中條目的索引:

<span style="white-space:pre">	</span>private int currentIndex = 0;
	private static int maxsize = 24;
	private static int minsize = 14;
	private ArrayList<View> arrayList = new ArrayList<View>();
建構函式也隨之改為了:
<span style="white-space:pre">	</span>protected AbstractWheelTextAdapter(Context context, int itemResource) {
		this(context, itemResource, NO_RESOURCE, 0, maxsize, minsize);
	}
<pre name="code" class="java"><span style="white-space:pre">	</span>protected AbstractWheelTextAdapter(Context context, int itemResource, int itemTextResource, int currentIndex,
			int maxsize, int minsize) {
		this.context = context;
		itemResourceId = itemResource;
		itemTextResourceId = itemTextResource;
		this.currentIndex = currentIndex;
		this.maxsize = maxsize;
		this.minsize = minsize;

		inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

其中currentIndex為初始化時選中字型變大的item的索引。

getView函式改為了:

<span style="white-space:pre">	</span>@Override
	public View getItem(int index, View convertView, ViewGroup parent) {
		if (index >= 0 && index < getItemsCount()) {
			if (convertView == null) {
				convertView = getView(itemResourceId, parent);
			}
			TextView textView = getTextView(convertView, itemTextResourceId);
			if (!arrayList.contains(textView)) { //儲存顯示文字的TextView的引用,方便在外部呼叫
				arrayList.add(textView);
			}
			if (textView != null) {
				CharSequence text = getItemText(index);
				if (text == null) {
					text = "";
				}
				textView.setText(text);

				if (index == currentIndex) {  //把當前選中item字型改大,其餘的變小
					textView.setTextSize(maxsize);
				} else {
					textView.setTextSize(minsize);
				}

				if (itemResourceId == TEXT_VIEW_ITEM_RESOURCE) {
					configureTextView(textView);
				}
			}
			return convertView;
		}
		return null;
	}
這樣Adapter就修改完了。

2、樣式的修改:

在WheelView中修改漸變顏色,中部為白色,向兩邊慢慢變暗

/** Top and bottom shadows colors */
	private static final int[] SHADOWS_COLORS = new int[] { 0xeeffffff, 0xeaffffff, 0x33ffffff };
wheel_val.xml檔案改為了
<shape xmlns:android="http://schemas.android.com/apk/res/android">
	<gradient
		android:startColor="#22ffffff"
		android:centerColor="#00ffffff"
		android:endColor="#22ffffff"
		android:angle="90" />
</shape>

wheel_bg.xml改為了空

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
</layer-list>
就實現了圖片中的效果,這樣對原始碼的修改就完成了。

3、選擇時間對話方塊的實現,程式碼如下:

佈局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ly_myinfo_changebirth"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00000000"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/ly_myinfo_changebirth_child"
        android:layout_width="300dip"
        android:layout_height="wrap_content"
        android:layout_marginLeft="27dip"
        android:layout_marginRight="27dip"
        android:background="@drawable/bg_dialog_selector"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/tv_share_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="14dip"
            android:layout_marginLeft="18dip"
            android:layout_marginTop="18dip"
            android:gravity="center_vertical"
            android:text="選擇日期"
            android:textColor="#000000"
            android:textSize="18sp" />
		<LinearLayout 
	        android:layout_width="match_parent"
	        android:layout_height="160dip"
	        android:orientation="horizontal"
	        android:layout_marginLeft="20dip"
	        android:layout_marginRight="20dip"
	        android:gravity="center_vertical">
	        <com.ywl5320.pickaddress.wheel.widget.views.WheelView
	            android:id="@+id/wv_birth_year"
	            android:layout_width="0dip"
	            android:layout_weight="1"
	            android:layout_height="match_parent"
	            android:layout_gravity="center_vertical"
	            />
	        <com.ywl5320.pickaddress.wheel.widget.views.WheelView
	            android:id="@+id/wv_birth_month"
	            android:layout_width="0dip"
	            android:layout_weight="1"
	            android:layout_height="match_parent"
	            android:layout_gravity="center_vertical"
	            />
	        <com.ywl5320.pickaddress.wheel.widget.views.WheelView
	            android:id="@+id/wv_birth_day"
	            android:layout_width="0dip"
	            android:layout_weight="1"
	            android:layout_height="match_parent"
	            android:layout_gravity="center_vertical"
	            />
	    </LinearLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="25dip"
            android:layout_marginBottom="21dip">

                <TextView
                    android:id="@+id/btn_myinfo_sure"
                    android:layout_width="77dip"
                    android:layout_height="33dip"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="15dip"
                    android:text="確認"
                    android:gravity="center"
                    android:textSize="16sp" />


                <TextView
                    android:id="@+id/btn_myinfo_cancel"
                    android:layout_width="77dip"
                    android:layout_height="33dip"
                    android:layout_toLeftOf="@+id/btn_myinfo_sure"
                    android:text="取消"
                    android:gravity="center"
                    android:textSize="16sp" />
        </RelativeLayout>
    </LinearLayout>

</LinearLayout>
對話方塊style:
<style name="ShareDialog" parent="@android:Theme.Dialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:backgroundDimEnabled">true</item>
    </style>
對話方塊原始碼:
package com.ywl5320.pickaddress;

import java.util.ArrayList;
import java.util.Calendar;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.ywl5320.pickaddress.wheel.widget.adapters.AbstractWheelTextAdapter;
import com.ywl5320.pickaddress.wheel.widget.views.OnWheelChangedListener;
import com.ywl5320.pickaddress.wheel.widget.views.OnWheelScrollListener;
import com.ywl5320.pickaddress.wheel.widget.views.WheelView;

/**
 * 日期選擇對話方塊
 * 
 * @author ywl
 *
 */
public class ChangeBirthDialog extends Dialog implements android.view.View.OnClickListener {

	private Context context;
	private WheelView wvYear;
	private WheelView wvMonth;
	private WheelView wvDay;

	private View vChangeBirth;
	private View vChangeBirthChild;
	private TextView btnSure;
	private TextView btnCancel;

	private ArrayList<String> arry_years = new ArrayList<String>();
	private ArrayList<String> arry_months = new ArrayList<String>();
	private ArrayList<String> arry_days = new ArrayList<String>();
	private CalendarTextAdapter mYearAdapter;
	private CalendarTextAdapter mMonthAdapter;
	private CalendarTextAdapter mDaydapter;

	private int month; //選中當前年有幾個月
	private int day; //選中當前月有幾天(分了閏年的)

	private int currentYear = getYear(); //得到當前年份
	private int currentMonth = 1;
	private int currentDay = 1;

	private int maxTextSize = 24; //字型最大值
	private int minTextSize = 14; //字型最小值

	private boolean issetdata = false; //判斷是否設定了預設時間,沒有就設定為當前時間

	private String selectYear; //選中的年
	private String selectMonth; //選中的月
	private String selectDay; //選中的日

	private OnBirthListener onBirthListener;

	public ChangeBirthDialog(Context context) {
		super(context, R.style.ShareDialog);
		this.context = context;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.dialog_myinfo_changebirth);
		wvYear = (WheelView) findViewById(R.id.wv_birth_year);
		wvMonth = (WheelView) findViewById(R.id.wv_birth_month);
		wvDay = (WheelView) findViewById(R.id.wv_birth_day);

		vChangeBirth = findViewById(R.id.ly_myinfo_changebirth);
		vChangeBirthChild = findViewById(R.id.ly_myinfo_changebirth_child);
		btnSure = (TextView) findViewById(R.id.btn_myinfo_sure);
		btnCancel = (TextView) findViewById(R.id.btn_myinfo_cancel);

		vChangeBirth.setOnClickListener(this);
		vChangeBirthChild.setOnClickListener(this);
		btnSure.setOnClickListener(this);
		btnCancel.setOnClickListener(this);

		if (!issetdata) {
			initData();
		}
		initYears();
<span style="white-space:pre">		</span>//初始化年,顯示可見條目數量,年份集合,當前設定年份、<span style="font-family: Arial, Helvetica, sans-serif;">字型大小</span>
		mYearAdapter = new CalendarTextAdapter(context, arry_years, setYear(currentYear), maxTextSize, minTextSize);
<span style="white-space:pre">		</span>//可見5條
		wvYear.setVisibleItems(5);
<span style="white-space:pre">		</span>//設定介面卡
		wvYear.setViewAdapter(mYearAdapter);
<span style="white-space:pre">		</span>//根據當前傳入的年份,設定顯示年份
		wvYear.setCurrentItem(setYear(currentYear));

		initMonths(month);
		mMonthAdapter = new CalendarTextAdapter(context, arry_months, setMonth(currentMonth), maxTextSize, minTextSize);
		wvMonth.setVisibleItems(5);
		wvMonth.setViewAdapter(mMonthAdapter);
		wvMonth.setCurrentItem(setMonth(currentMonth));

		initDays(day);
		mDaydapter = new CalendarTextAdapter(context, arry_days, currentDay - 1, maxTextSize, minTextSize);
		wvDay.setVisibleItems(5);
		wvDay.setViewAdapter(mDaydapter);
		wvDay.setCurrentItem(currentDay - 1);

<span style="white-space:pre">		</span>//為年份選中新增change事件,根據選中年份,聯動設定月份
		wvYear.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem());
				selectYear = currentText;
				setTextviewSize(currentText, mYearAdapter);
				currentYear = Integer.parseInt(currentText);
				setYear(currentYear);
				initMonths(month);
				mMonthAdapter = new CalendarTextAdapter(context, arry_months, 0, maxTextSize, minTextSize);
				wvMonth.setVisibleItems(5);
				wvMonth.setViewAdapter(mMonthAdapter);
				wvMonth.setCurrentItem(0);
			}
		});

<span style="white-space:pre">		</span>//新增滾動事件,呼叫adapter中的顯示文字集合來改變字型大小
		wvYear.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) mYearAdapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, mYearAdapter);
			}
		});

		wvMonth.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem());
				selectMonth = currentText;
				setTextviewSize(currentText, mMonthAdapter);
				setMonth(Integer.parseInt(currentText));
				initDays(day);
				mDaydapter = new CalendarTextAdapter(context, arry_days, 0, maxTextSize, minTextSize);
				wvDay.setVisibleItems(5);
				wvDay.setViewAdapter(mDaydapter);
				wvDay.setCurrentItem(0);
			}
		});

		wvMonth.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) mMonthAdapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, mMonthAdapter);
			}
		});

		wvDay.addChangingListener(new OnWheelChangedListener() {

			@Override
			public void onChanged(WheelView wheel, int oldValue, int newValue) {
				// TODO Auto-generated method stub
				String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, mDaydapter);
				selectDay = currentText;
			}
		});

		wvDay.addScrollingListener(new OnWheelScrollListener() {

			@Override
			public void onScrollingStarted(WheelView wheel) {
				// TODO Auto-generated method stub

			}

			@Override
			public void onScrollingFinished(WheelView wheel) {
				// TODO Auto-generated method stub
				String currentText = (String) mDaydapter.getItemText(wheel.getCurrentItem());
				setTextviewSize(currentText, mDaydapter);
			}
		});

	}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>//初始化年份,可以把1950設定為一個變數,方便動態設定
	public void initYears() {
		for (int i = getYear(); i > 1950; i--) {
			arry_years.add(i + "");
		}
	}
<span style="white-space:pre">	</span>//初始化月份
	public void initMonths(int months) {
		arry_months.clear();
		for (int i = 1; i <= months; i++) {
			arry_months.add(i + "");
		}
	}
<span style="white-space:pre">	</span>//出事話天日
	public void initDays(int days) {
		arry_days.clear();
		for (int i = 1; i <= days; i++) {
			arry_days.add(i + "");
		}
	}

	private class CalendarTextAdapter extends AbstractWheelTextAdapter {
		ArrayList<String> list;

		protected CalendarTextAdapter(Context context, ArrayList<String> list, int currentItem, int maxsize, int minsize) {
			super(context, R.layout.item_birth_year, NO_RESOURCE, currentItem, maxsize, minsize);
			this.list = list;
			setItemTextResource(R.id.tempValue);
		}

		@Override
		public View getItem(int index, View cachedView, ViewGroup parent) {
			View view = super.getItem(index, cachedView, parent);
			return view;
		}

		@Override
		public int getItemsCount() {
			return list.size();
		}

		@Override
		protected CharSequence getItemText(int index) {
			return list.get(index) + "";
		}
	}

<span style="white-space:pre">	</span>//暴露給activity的回撥藉口,用於獲取選擇的結果
	public void setBirthdayListener(OnBirthListener onBirthListener) {
		this.onBirthListener = onBirthListener;
	}

	@Override
	public void onClick(View v) {

		if (v == btnSure) {
			if (onBirthListener != null) {
				onBirthListener.onClick(selectYear, selectMonth, selectDay);
			}
		} else if (v == btnSure) {

		} else if (v == vChangeBirthChild) {
			return;
		} else {
			dismiss();
		}
		dismiss();

	}

	public interface OnBirthListener {
		public void onClick(String year, String month, String day);
	}

	/**
	 * 設定字型大小
	 * 
	 * @param curriteItemText
	 * @param adapter
	 */
	public void setTextviewSize(String curriteItemText, CalendarTextAdapter adapter) {
		ArrayList<View> arrayList = adapter.getTestViews();
		int size = arrayList.size();
		String currentText;
		for (int i = 0; i < size; i++) {
			TextView textvew = (TextView) arrayList.get(i);
			currentText = textvew.getText().toString();
			if (curriteItemText.equals(currentText)) {
				textvew.setTextSize(maxTextSize);
			} else {
				textvew.setTextSize(minTextSize);
			}
		}
	}

	public int getYear() {
		Calendar c = Calendar.getInstance();
		return c.get(Calendar.YEAR);
	}

	public int getMonth() {
		Calendar c = Calendar.getInstance();
		return c.get(Calendar.MONTH) + 1;
	}

	public int getDay() {
		Calendar c = Calendar.getInstance();
		return c.get(Calendar.DATE);
	}

	public void initData() {
		setDate(getYear(), getMonth(), getDay());
		this.currentDay = 1;
		this.currentMonth = 1;
	}

	/**
	 * 設定年月日
	 * 
	 * @param year
	 * @param month
	 * @param day
	 */
	public void setDate(int year, int month, int day) {
		selectYear = year + "";
		selectMonth = month + "";
		selectDay = day + "";
		issetdata = true;
		this.currentYear = year;
		this.currentMonth = month;
		this.currentDay = day;
		if (year == getYear()) {
			this.month = getMonth();
		} else {
			this.month = 12;
		}
		calDays(year, month);
	}

	/**
	 * 設定年份
	 * 
	 * @param year
	 */
	public int setYear(int year) {
		int yearIndex = 0;
		if (year != getYear()) {
			this.month = 12;
		} else {
			this.month = getMonth();
		}
		for (int i = getYear(); i > 1950; i--) {
			if (i == year) {
				return yearIndex;
			}
			yearIndex++;
		}
		return yearIndex;
	}

	/**
	 * 設定月份
	 * 
	 * @param year
	 * @param month
	 * @return
	 */
	public int setMonth(int month) {
		int monthIndex = 0;
		calDays(currentYear, month);
		for (int i = 1; i < this.month; i++) {
			if (month == i) {
				return monthIndex;
			} else {
				monthIndex++;
			}
		}
		return monthIndex;
	}

	/**
	 * 計算每月多少天
	 * 
	 * @param month
	 * @param leayyear
	 */
	public void calDays(int year, int month) {
		boolean leayyear = false;
		if (year % 4 == 0 && year % 100 != 0) {
			leayyear = true;
		} else {
			leayyear = false;
		}
		for (int i = 1; i <= 12; i++) {
			switch (month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				this.day = 31;
				break;
			case 2:
				if (leayyear) {
					this.day = 29;
				} else {
					this.day = 28;
				}
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				this.day = 30;
				break;
			}
		}
		if (year == getYear() && month == getMonth()) {
			this.day = getDay();
		}
	}
}

4、選擇地址過程基本一致,就不在這裡贅述了,唯一區別就是獲取地址源的時候,是通過解析json資料獲取的,我會上傳原始碼,無積分下載的。

好的這樣就完成了這種看似高大上的效果 哈哈哈     原始碼下載