Android CheckBox多選時間段,合并重復時間
來自: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0123/3907.html
之前拿到了一個問題,在訂購機票界面中需要一個時間篩選的功能,需求是讓用戶能夠自由組合時間段,并且相鄰時間段要合并,盡量少用if else 嵌套,可能問題看上去蠻簡單,但對我這種沒學過算法的還是要動一番腦子的,最終效果是這樣
</div>
具體需求:
點擊不不限的時候其他時間全部取消
兩個相鄰的時間勾上的時候中間相同的部分去掉,如00:00-14:00
四個時間全部選上的時候,時間的勾全部去掉,然后顯示不限
說下思路,這里面有5個CheckBox,既然是要根據它們的選中狀態來組合改變數據,那怎么做?我想到了創建五個時間對象TimeTree,其中第一個和下面四個時間需要區分開來,所以加入一個int屬性,名字就叫type,有0和1兩個值。
對于下面4個TimeTree,肯定需要有start和end兩個String屬性,分別對應起始時間和結束時間,如tt1的start是"0:00",end是"12:00"。
另外每個對象中都應該持有對左右兩個TimeTree對象的引用LeftTimeTree和RightTimeTree,這樣方便接下來判斷是否為相鄰時間。當然一頭一尾兩個時間分別只有RightTimeTree和LeftTimeTree。
其余部分都很簡單,主要就是合并重復時間花了一番功夫,我的做法是用一個集合保存所有選中的TimeTree,只有下面4個會保存到集合中,點擊'不限'會清空這個集合。
在集合中有多個元素時,首先遍歷集合,如果LeftTimeTree為空或者LeftTimeTree不包含在這個集合中,說明這是一個 頭時間點 ,記錄下它的start,關鍵是求end,這里我寫了一個遞歸方法,如果RightTimeTree包含在集合中,end就是RightTimeTree的end,再對RightTimeTree的end如此循環,就得到了最終應該顯示的end。下面是代碼
TimeTree類
public class TimeTree {
public int type = 0;
public String start;
public String end;
public String timeStr;
public TimeTree leftTime;
public TimeTree rightTime;
}
主界面
public class MainThreeAct extends Activity implements OnClickListener {
List<String> timeNodes = Arrays.asList("0:00", "12:00", "14:00", "18:00", "24:00");
private TextView tv;
private LinearLayout ll;
private CheckBox cb_012;
private CheckBox cb_1214;
private CheckBox cb_1418;
private CheckBox cb_1824;
private CheckBox cb_unlimit;
// CheckBox集合
private List<CheckBox> cbs;
// 時間對象集合
private List<TimeTree> times;
// 選中的時間對象集合
private List<TimeTree> selectedTimes = new ArrayList<TimeTree>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_three_activity);
initVariables();
initViews();
}
private void initVariables() {
TimeTree tt0 = new TimeTree();
TimeTree tt1 = new TimeTree();
TimeTree tt2 = new TimeTree();
TimeTree tt3 = new TimeTree();
TimeTree tt4 = new TimeTree();
times = Arrays.asList(tt0, tt1, tt2, tt3, tt4);
for (int i = 1; i < times.size(); i++) {
// type用來區分是不限(0),還是具體時間(1)
times.get(i).type = 1;
// 為每一個時間對象添加開始和結束時間
times.get(i).start = timeNodes.get(i - 1);
times.get(i).end = timeNodes.get(i);
times.get(i).timeStr = timeNodes.get(i - 1) + "-" + times.get(i);
// 為每一個時間對象添加相鄰時間對象
times.get(i).leftTime = i - 1 <= 0 ? null : times.get(i - 1);
times.get(i).rightTime = i + 1 >= times.size() ? null : times.get(i + 1);
}
}
private void initViews() {
tv = (TextView) findViewById(R.id.tv);
ll = (LinearLayout) findViewById(R.id.ll);
cb_012 = (CheckBox) findViewById(R.id.cb012);
cb_1214 = (CheckBox) findViewById(R.id.cb1214);
cb_1418 = (CheckBox) findViewById(R.id.cb1418);
cb_1824 = (CheckBox) findViewById(R.id.cb1824);
cb_unlimit = (CheckBox) findViewById(R.id.cb_unlimit);
cbs = Arrays.asList(cb_unlimit, cb_012, cb_1214, cb_1418, cb_1824);
cb_012.setOnClickListener(this);
cb_1214.setOnClickListener(this);
cb_1418.setOnClickListener(this);
cb_1824.setOnClickListener(this);
cb_unlimit.setOnClickListener(this);
}
/**
* CheckBox的點擊監聽
*/
@Override
public void onClick(View v) {
CompoundButton buttonView = (CompoundButton) v;
boolean isChecked = buttonView.isChecked();
// 獲取CheckBox的位置索引值
int index = ll.indexOfChild(buttonView);
// 根據位置索引,獲取對應的時間對象
TimeTree timeTree = times.get(index);
// 取消CheckBox
if (!isChecked) {
if (index == 0) {
return;
}
// 更新選中時間的集合
selectedTimes.remove(timeTree);
if (selectedTimes.size() == 0) {
// 不限時間
unlimitTime();
return;
}
// 更新TextView
setText();
return;
}
// 選中CheckBox
// 選中的是'不限'
if (timeTree.type == 0) {
unlimitTime();
return;
}
// 選中了具體時間,首先將對應的時間對象記錄下來
selectedTimes.add(timeTree);
// 全選中時不限時間
if (selectedTimes.size() == times.size() - 1) {
unlimitTime();
return;
}
// 取消全選
cbs.get(0).setChecked(false);
// 更新TextView
setText();
}
/**
* 不限時間
*/
private void unlimitTime() {
selectedTimes.clear();
for (int i = 1; i < cbs.size(); i++) {
cbs.get(i).setChecked(false);
}
cbs.get(0).setChecked(true);
tv.setText("不限");
}
/**
* 根據選中的時間,來更新TextView
*/
private void setText() {
// 排序
Collections.sort(selectedTimes, new Comparator<TimeTree>() {
@Override
public int compare(TimeTree lhs, TimeTree rhs) {
return lhs.start.compareTo(rhs.start);
}
});
StringBuffer sb = new StringBuffer();
for (int i = 0; i < selectedTimes.size(); i++) {
TimeTree timeTree = selectedTimes.get(i);
if (timeTree.leftTime == null || !selectedTimes.contains(timeTree.leftTime)) {
String start = timeTree.start;
String end = timeTree.end;
// 獲取合并后的endTime
end = updateEndTime(timeTree);
sb.append(start + "-" + end + ",");
}
}
String text = sb.toString();
tv.setText(text.substring(0, text.length() - 1));
}
/**
* 遞歸,獲取合并后的endTime
*/
private String updateEndTime(TimeTree timeTree) {
String end = timeTree.end;
if (timeTree.rightTime != null && selectedTimes.contains(timeTree.rightTime)) {
end = updateEndTime(timeTree.rightTime);
}
return end;
}
}</pre> </div>