Android Development notes: ListView Refresh Sequence of questions detailed _android

Source: Internet
Author: User
Background
A typical ListView, each item displays a TextView, represents a task, needs to implement two edits: one is to use a checkbox to identify the task has been completed, another to implement the edit is delete task. The completed checkbox is placed directly in the layout, but the deletion does not want to use ContextMenu for editing, and for lists like iOS, it is triggered by gestures to each item in the list. This implementation is not difficult, you can use a Viewswitcher,checkbox and delete button is put in which, let Viewswitcher to control the display of which, normally show a checkbox, hide the Delete button, and then click the item when the Show Delete button, Hide the checkbox, which is also more in line with the operating habits, you can delete one entry.
the way to achieve this is as follows:
Copy Code code as follows:

public class Listorderactivity extends activity {
Private ListView mtasklist;
Private EditText Maddtaskeditor;
Private Layoutinflater mfactory;

@Override
public void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (r.layout.list_activity);

MFactory = Layoutinflater.from (Getapplication ());
Mtasklist = (ListView) Findviewbyid (r.id.task_list);
Final View Headerview = mfactory.inflate (R.layout.header_view, NULL);
Mtasklist.addheaderview (Headerview);
Maddtaskeditor = (edittext) Headerview.findviewbyid (r.id.task_editor);
Maddtaskeditor.setonkeylistener (New Onkeylistener () {
@Override
public Boolean OnKey (view view, int keycode, keyevent event) {
if (keycode = = Keyevent.keycode_dpad_center | | keycode = = keyevent.keycode_enter) {
Finish editing
Final Inputmethodmanager InputManager = (inputmethodmanager) getsystemservice (Context.input_method_service);
Inputmanager.hidesoftinputfromwindow (Getcurrentfocus (). Getwindowtoken (), 0);
Final String Text = Maddtaskeditor.gettext (). toString ();
if (! Textutils.isempty (text)) {
Final contentvalues values = new Contentvalues (1);
Values.put (taskcolumns.task, text);
Values.put (Taskcolumns.type, task.type_today);
Getcontentresolver (). Insert (Task.content_uri, values);
}
Maddtaskeditor.settext ("");
}
return false;
}
});
Final Cursor Cursor = Getcontentresolver (). Query (Task.content_uri, task.projection, taskcolumns.type + "=" + task.type_t Oday, NULL, NULL);
Final Taskadapter adapter = new Taskadapter (getapplication (), cursor);
Mtasklist.setadapter (adapter);
}

Private class Taskadapter extends CursorAdapter {
Private Cursor mcursor;

Public Taskadapter (context, Cursor c) {
Super (context, c);
Mcursor = C;
}

@Override
public void BindView (view view, context, Cursor Cursor) {
if (view = = null) {
View = Mfactory.inflate (R.layout.today_task_item, NULL);
}
Final Viewswitcher switcher = (viewswitcher) View.findviewbyid (R.id.action_switcher);
if (switcher.getdisplayedchild () = = 1) {
Switcher.clearanimation ();
Switcher.showprevious ();
Switcher.clearanimation ();
//            }
Final CheckBox toggle = (CheckBox) View.findviewbyid (R.id.action_toggle_done);
Final short done = Cursor.getshort (Projectionindex.done);
Final int id = cursor.getint (projectionindex.id);
Toggle.setoncheckedchangelistener (NULL);
toggle.setchecked (done!= 0);
Toggle.setoncheckedchangelistener (New Oncheckedchangelistener () {
@Override
public void oncheckedchanged (Compoundbutton view, Boolean checked) {
Final URI uri = Contenturis.withappendedid (Task.content_uri, id);
Final contentvalues values = new Contentvalues (1);
Values.put (Taskcolumns.done, checked 1:0);
Getcontentresolver (). Update (URI, values, NULL, NULL);
}
});
View.setonclicklistener (New Onclicklistener () {
@Override
public void OnClick (View v) {
Switcher.shownext ();
if (switcher.getdisplayedchild () = = 0) {
Switcher.getinanimation (). Setanimationlistener (NULL);
Return
}
Final ImageView delete = (ImageView) V.findviewbyid (r.id.action_delete_task);
Delete.setonclicklistener (New Onclicklistener () {
@Override
public void OnClick (View v) {
Switcher.getinanimation (). Setanimationlistener (New Animationlistener () {
@Override
public void Onanimationend (Animation Animation) {
Switcher.getinanimation (). Setanimationlistener (NULL);
Final URI uri = Contenturis.withappendedid (Task.content_uri, id);
Getcontentresolver (). Delete (URI, NULL, NULL);
}

@Override
public void Onanimationrepeat (Animation Animation) {
}

@Override
public void Onanimationstart (Animation Animation) {
}
});
Switcher.showprevious ();
}
});
}
});
TextView task = (TextView) View.findviewbyid (r.id.task);
Final String taskcontent = cursor.getstring (Projectionindex.task);
if (done!= 0) {
Final spannable style = new spannablestring (taskcontent);
Style.setspan (New Strikethroughspan (), 0, Taskcontent.length (), spannable.span_inclusive_inclusive);
Style.setspan (New Stylespan (Typeface.italic), 0, Taskcontent.length (), spannable.span_inclusive_inclusive);
Task.settext (style);
Task.settextappearance (Getapplication (), r.style.done_task_item_text);
} else {
Task.settext (taskcontent);
Task.settextappearance (Getapplication (), r.style.task_item_text);
}
}
@Override
Public View Newview (context, Cursor Cursor, ViewGroup parent) {
View view = Mfactory.inflate (R.layout.today_task_item, NULL);
return view;
}

@Override
public void oncontentchanged () {
Mcursor.requery ();
}
}
}

Copy Code code as follows:

<?xml version= "1.0" encoding= "Utf-8"?>
<linearlayout xmlns:android= "Http://schemas.android.com/apk/res/android"
Android:layout_width= "Fill_parent"
android:layout_height= "Fill_parent"
android:orientation= "Vertical"
Android:background= "#f0f0f0"
Android:paddingbottom= "5dip"
android:paddingleft= "12dip"
android:paddingright= "12dip"
android:paddingtop= "5dip" >
<listview
Android:id= "@+id/task_list"
Android:layout_width= "Fill_parent"
android:layout_height= "Fill_parent"
android:divider= "@color/divider"
android:dividerheight= "0.6dip"/>
</LinearLayout>

Copy Code code as follows:

<?xml version= "1.0" encoding= "Utf-8"?>
<linearlayout
Xmlns:android= "Http://schemas.android.com/apk/res/android"
android:orientation= "Horizontal"
Android:layout_width= "Fill_parent"
android:layout_height= "Wrap_content"
android:layout_gravity= "Center"
android:gravity= "Center" >
<viewswitcher android:id= "@+id/action_switcher"
Android:layout_width= "Wrap_content"
android:layout_height= "Wrap_content"
android:layout_gravity= "Center"
android:gravity= "Center"
android:inanimation= "@anim/action_switcher_in"
android:outanimation= "@anim/action_switcher_out" >
<checkbox android:id= "@+id/action_toggle_done"
Android:layout_width= "Wrap_content"
android:layout_height= "Wrap_content"
android:gravity= "Center"
android:layout_gravity= "Center"/>
<imageview android:id= "@+id/action_delete_task"
android:src= "@drawable/ic_delete"
Android:layout_width= "48dip"
android:layout_height= "48dip"
android:contentdescription= "@string/delete_description"
android:gravity= "Center"
android:layout_gravity= "Center"
Android:scaletype= "Center"/>
</ViewSwitcher>
<textview android:id= "@+id/task"
style= "@style/task_item_text"/>
</LinearLayout>



problem
But there is a problem, if one of the entries is in the deleted state, then add a new task, or click on another entry checkbox, the status of the entry will be confused, the original in the normal state of the item will be in the deleted state!
cause Analysis
It was initially thought to be a data problem because the handling of the event was an anonymous class that might point to incorrect external data, and all data was found to be correct through print debugging. Finally, by adding log information in the BindView method, we found the reason: Each listview refresh BindView sequence is not the same, the original in the 3rd of the Child view, refresh may be placed in the 1th position. The display state of the viewswitcher is maintained by itself, which means that the state it should display is not saved outside the view, so when the data changes (the checkbox causes data changes), the list is refreshed. A child view that was previously in the deleted state (possibly in the 4th position) may now turn into a 2nd position, causing the second to be deleted and the fourth to be in a normal state.
Solution
There is no perfect solution to this problem, can only do a workaround method: that is, every time you refresh the BindView delete state, all replaced by the default state, so at least not a state of chaos situation. However, you will still see that the deletion will flash.
A complete solution to this problem is to avoid using this design when there are other ways to cause data change. This design applies only if the entire list is deleted and there is no other way to cause the list to be refreshed, when the direct handle view is removed from the ListView and no confusion occurs.

It also explains why we have to add data to the child view every time we bindview, instead of just creating the child view Add data. Because the order is not necessarily the previous order each time the BindView is refreshed, you must add the data again. And the data is usually shared with the view, or in the database, or other forms, will exist in a particular order, it will not change because of the view refresh, so in order to not use the user feel state disorder, you have to be in the order of the data to fill the view data.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.