统计界面RecordFragment中的业务逻辑涉及到三个方面:新建任务,每日签到和删除任务。有上面三个中的任何一个操作时,统计界面都要做出相应的更新。其中删除操作在统计界面中进行。
这里参考了文章中实现自定义ListView的形式。
TaskBean类在上一篇文章中已经介绍过了,下面定义一个接口
ITaskFinder:
public interface ITaskFinder {
List<TaskBean> findAllTask();
}
接口中只有一个方法
findAllTask,获取所有任务的列表。
接口实现类
ITaskFinderImpl如下:
@EBean
public class ITaskFinderImpl implements ITaskFinder {
@RootContext
Context context;
private MyDatabaseHelper dbHelper = null;
@Override
public List<TaskBean> findAllTask() {
if ( dbHelper == null) {
dbHelper = new MyDatabaseHelper( context, "di.db3", 1);
}
return DailyInsistDao. getTasks(dbHelper, 0, -1);
}
}
因为RecordFragment要列出所有的任务并统计它们的信息,所以我们需要一个
TaskItemAdapter来绑定数据到视图上,
TaskItemView是列表项的视图,如下:
@EViewGroup(R.layout.task_item )
public class TaskItemView extends LinearLayout {
@ViewById
TextView tv_rate, tv_item_title, tv_start_to_end;
@ViewById
LinearLayout ll_rec_rate, ll_main;
@StringRes
String rate;
@DrawableRes
Drawable orange_rec, blue_rec, gray_rec, btn_up, btn_down;
@ViewById
Button btn_toggle;
/*
* set toggle button to control show or hide delete part
*/
@ViewById
RelativeLayout rl_del;
/*
* for delete
*/
private int taskId;
public TaskItemView(Context context) {
super(context);
}
public void bind(TaskBean task) {
taskId = task.getTaskId();
/*
* show rate view
*/
tv_rate.setText(String. format(rate, task.getCompleted(),
task.getDuring()));
/*
* show title view
*/
tv_item_title.setText(task.getContent());
/*
* show rectangle rate
*/
ll_rec_rate.removeAllViews();
/*
* the task is finished
*/
if (task.getCompleted() == task.getDuring()) {
for ( int i = 0, count = task.getDuring(); i < count; i++) {
ll_rec_rate.addView(getRegBackgroundByDrawable( ll_rec_rate,
orange_rec));
}
} else {
/*
* if the task is not finished, completed parts use blue rectangle
* and rest use gray one
*/
for ( int i = 0, count = task.getCompleted(); i < count; i++) {
ll_rec_rate.addView(getRegBackgroundByDrawable( ll_rec_rate,
blue_rec));
}
for ( int i = 0, count = task.getDuring() - task.getCompleted(); i < count; i++) {
ll_rec_rate.addView(getRegBackgroundByDrawable( ll_rec_rate,
gray_rec));
}
}
/*
* set start to end date view
*/
tv_start_to_end
.setText(task.getStartDate() + " - " + task.getEndDate());
}
@SuppressWarnings("deprecation")
private TextView getRegBackgroundByDrawable(LinearLayout ll_rec_rate,
Drawable rec) {
/*
* set width, height, background and layout
*/
TextView tv_rec = new TextView(getContext());
tv_rec.setWidth(Util. dip2px(getContext(), 7));
tv_rec.setHeight(Util. dip2px(getContext(), 7));
tv_rec. setBackgroundDrawable(rec);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT ,
LayoutParams. WRAP_CONTENT);
lp.setMargins(0, 0, Util. dip2px(getContext(), 5), 0);
tv_rec.setLayoutParams(lp);
return tv_rec;
}
@Click
protected void btn_del() {
new AlertDialog.Builder(getContext())
.setMessage( "Sure to DELETE?")
.setNegativeButton( "Cancel", null)
.setPositiveButton( "DELETE",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
deleteTask();
}
}).create().show();
}
@SuppressWarnings("deprecation")
@Click
void ll_main() {
if ( rl_del.getVisibility() == View. GONE) {
rl_del.setVisibility(View. VISIBLE);
btn_toggle. setBackgroundDrawable(btn_up);
} else {
rl_del.setVisibility(View. GONE);
btn_toggle. setBackgroundDrawable(btn_down);
}
}
protected void deleteTask() {
DailyInsistDao. deleteTask(new MyDatabaseHelper(getContext(), "di.db3" ,
1), taskId);
getContext().sendBroadcast( new Intent(Actions.ACTION_UPDATE_INFO ));
}
}
删除任务后将发广播通知RecordFragment界面更新数据和界面。
列表项的布局
task_item.xml如下:
<?xml version="1.0" encoding= "utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_main"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:background="@android:color/white"
android:clickable="true"
android:orientation="vertical" >
<RelativeLayout
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_marginBottom="10dp" >
<TextView
android:id= "@+id/tv_rate"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_marginLeft= "30dp"
android:layout_marginTop= "10dp"
android:text= "@string/rate"
android:textColor= "@color/record_title_text_dark"
android:textSize= "@dimen/text_title" />
<TextView
android:id= "@+id/tv_item_title"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignBaseline="@+id/tv_rate"
android:layout_alignBottom= "@+id/tv_rate"
android:layout_marginLeft= "16dp"
android:layout_toRightOf= "@+id/tv_rate"
android:text= "@string/str_title"
android:textColor= "@color/record_title_text_dark"
android:textSize= "@dimen/text_subtitle" />
<Button
android:id= "@+id/btn_toggle"
android:layout_width= "25dp"
android:layout_height= "25dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight= "25dp"
android:background= "@drawable/btn_down" />
<LinearLayout
android:id= "@+id/ll_rec_rate"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_below= "@+id/tv_rate"
android:layout_marginLeft= "30dp"
android:layout_marginTop= "7dp" >
<!-- <TextView -->
<!-- android:layout_width="7dp" -->
<!-- android:layout_height="7dp" -->
<!-- android:layout_marginRight="5dp" -->
<!-- android:background="@drawable/gray_rec" /> -->
</LinearLayout >
</RelativeLayout >
<RelativeLayout
android:id= "@+id/rl_del"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:layout_marginBottom="10dp"
android:visibility= "gone" >
<TextView
android:id= "@+id/tv_start_to_end"
android:layout_width= "wrap_content"
android:layout_height= "wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft= "30dp"
android:text= "@string/str_something"
android:textColor= "@color/record_title_text_dark"
android:textSize= "@dimen/text_subtitle" />
<Button
android:id= "@+id/btn_del"
style= "@style/btn_del_style"
android:layout_width= "81dp"
android:layout_height= "37dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight= "30dp"
android:background= "@drawable/orange_del_button"
android:text= "@string/str_delete" />
</RelativeLayout >
</LinearLayout>
TaskItemAdapter适配器直接操作
ITaskFinder接口的实现类获取任务列表,然后绑定数据,创建相应视图:
@EBean
public class TaskItemAdapter extends BaseAdapter {
@RootContext
Context context;
@Bean(ITaskFinderImpl. class)
ITaskFinder iTaskFinder;
private List<TaskBean> taskList;
@AfterInject
void initAdapter() {
taskList = iTaskFinder.findAllTask();
}
/**
*
* @Method: getView
* @Description: The adapter directly manipulates task list to bind its data
* and create the corresponding views
* @param pos
* @param convertView
* @param parent
* @return
* @see android.widget.Adapter#getView(int, android.view.View,
* android.view.ViewGroup)
*/
@Override
public View getView( int pos, View convertView, ViewGroup parent) {
TaskItemView taskItemView;
if (convertView == null) {
taskItemView = TaskItemView_. build(context);
} else {
taskItemView = (TaskItemView) convertView;
}
taskItemView.bind(getItem(pos));
return taskItemView;
}
@Override
public int getCount() {
return taskList.size();
}
@Override
public TaskBean getItem( int pos) {
return taskList.get(pos);
}
@Override
public long getItemId( int pos) {
return pos;
}
/**
*
* @Method: resetTaskList
* @Description: reset the task list to update the listview
* @param @param taskList
* @return void
* @throws
*/
public void resetTaskList(List<TaskBean> taskList) {
this. taskList.clear();
this. taskList.addAll(taskList);
this.notifyDataSetChanged();
}
}
使用这种方法的话就不需要View Holder 模式了
resetTaskList方法用来重置数据后刷新界面。
最后就是RecordFragment了,实现了具体的功能:
使用了一个全局的SharePreference,由 changed 变量保存数据改变状态(使用AndroidAnnotation):
@EFragment(R.layout.frag_record )
public class RecordFragment extends BaseFragment {
private MyDatabaseHelper dbHelper = null;
@ViewById
TextView tv_rounds, tv_completed_tasks, tv_days;
@ViewById
ListView lv_task_list;
@Bean
TaskItemAdapter adapter;
@AfterViews
void initAdapter() {
if ( dbHelper == null) {
dbHelper = new MyDatabaseHelper(this.getActivity(), "di.db3" , 1);
}
lv_task_list.setAdapter( adapter);
updateInfo();
registerUpdateInfoReceiver();
}
@Override
public void show() {
initView();
}
@Pref
GlobalPrefBean_ globalPrefBean;
void initView () {
boolean changed = globalPrefBean.changed().get();
if (changed) {
/*
* update Fragment
*/
updateInfo();
}
}
private void updateInfo() {
/*
* get data from local database
*/
List<TaskBean> taskList = DailyInsistDao.getTasks(dbHelper, 0, -1);
/*
* update UI
*/
tv_rounds.setText(taskList.size() + "");
int completedTasks = 0, completedDays = 0;
for (TaskBean task : taskList) {
if (task.getCompleted() == task.getDuring()) {
completedTasks++;
}
completedDays += task.getCompleted();
}
tv_completed_tasks.setText(completedTasks + "");
tv_days.setText(completedDays + "");
/*
* reset adapter
*/
adapter.resetTaskList(taskList);
}
/**
*
* @ClassName UpdateInfoReceiver
* @Description when delete a task, this broadcast receiver will receive it
* @author kiyonlin@163. com
* @date 2014- 1- 17 下午2:31:02
*/
public class UpdateInfoReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
return;
}
if (com.kiyonlin.utils.Actions.ACTION_UPDATE_INFO .equals(intent
.getAction())) {
updateInfo();
}
}
}
protected UpdateInfoReceiver updateInfoReceiver;
protected void registerUpdateInfoReceiver() {
if ( updateInfoReceiver == null) {
updateInfoReceiver = new UpdateInfoReceiver();
}
IntentFilter filter = new IntentFilter(Actions.ACTION_UPDATE_INFO );
getActivity().registerReceiver( updateInfoReceiver, filter);
}
@UiThread
void showShortToastMsg(String msg) {
Toast. makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
}
@UiThread
void showLongToastMsg(String msg) {
Toast. makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
}
}
使用了一个全局的SharePreference,由 changed 变量保存数据改变状态(使用AndroidAnnotation):
@SharedPref(value = SharedPref .Scope.UNIQUE)
public interface GlobalPrefBean {
boolean changed();
}