android in practice_Managing a stateful list/Header and footer views
2012-12-04 11:47
351 查看
(1)ViewHolder pattern, which will make your list render significantly faster and hence scroll more smoothly.
(2) Adapter, the views for our ListView are bound to the data source we’ll use a static movies file, via our Adapter.
list is backed by data coming from an adapter.
When having to maintain dynamic data that can change in reaction to view events (or any other event), you’ll have to create your own adapter implementation that performs the following tasks:
If the data wrapped by the adapter changes, it must inform the view about these changes so it can redraw itself.
If the user interacts with the view in a way that’s supposed to update the data, we must inform the adapter about this and make the according changes to the data source.
(3)Header and footer views
must add all header and footer views before adding any data to your list (via ListView.setAdapter);
can’t rely on Adapter.getCount anymore
MyMovies.project
layout\acitivity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/title"
android:layout_width="fill_parent"
android:layout_height="45px"
android:scaleType="fitXY" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
layout\movie_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical">
<CheckedTextView
android:id="@android:id/text1"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="0.9"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:checkMark="?android:attr/listChoiceIndicatorMultiple" />
</LinearLayout>
layout\list_footer.xml
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:text="Back to top"
android:onClick="backToTop" />
android:onClick="backToTop" :look for a public method called backToTop defined in our activity, which takes a single View object as a parameter.
store them as an array resource in our application.
After all, application code is supposed to contain logic, not data.
values\movies.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<string-array name="movies">
<item id="1">The Shawshank Redemption (1994)</item>
<item>The Godfather (1972)</item>
<item>The Godfather, Part II (1974)</item>
<item>The Good, the Bad, and the Ugly (1966) (It.)</item>
<item>Pulp Fiction (1994)</item>
<item>Schindler\'s List (1993)</item>
<item>12 Angry Men (1957)</item>
<item>One Flew Over The Cuckoo\'s Nest (1975)</item>
<item>The Dark Knight (2009)</item>
<item>Star Wars: Episode V: The Empire Strikes Back (1980)</item>
<item>Casablanca (1942)</item>
<item>Star Wars (1977)</item>
<item>The Lord of the Rings: The Return of the King (2003)</item>
<item>The Seven Samurai (1954) (Jp.)</item>
<item>GoodFellas (1990)</item>
<item>Rear Window (1954)</item>
<item>City of God (2002, Brazil/Fr.)</item>
<item>Raiders of the Lost Ark (1981)</item>
<item>Fight Club (1999)</item>
<item>The Lord of the Rings: The Fellowship of the Ring (2001)</item>
<item>Once Upon a Time in the West (1969) (It.)</item>
<item>The Usual Suspects (1995)</item>
<item>Psycho (1960)</item>
<item>The Silence of the Lambs (1991)</item>
<item>Sunset Boulevard (1950)</item>
<item>The Matrix (1999)</item>
<item>Memento (2000)</item>
<item>Dr. Strangelove or: How I Learned To Stop Worrying and Love the Bomb (1964)</item>
<item>North By Northwest (1959)</item>
<item>Se7en (1995)</item>
<item>It\'s A Wonderful Life (1946)</item>
<item>The Lord of the Rings: The Two Towers (2002)</item>
<item>Citizen Kane (1941)</item>
<item>Leon, aka The Professional (1994) (Fr.)</item>
<item>Apocalypse Now (1979)</item>
<item>American Beauty (1999)</item>
<item>American History X (1998)</item>
<item>Taxi Driver (1976)</item>
<item>Forrest Gump (1994)</item>
<item>Vertigo (1958)</item>
<item>Lawrence of Arabia (1962)</item>
<item>Up (2009)</item>
<item>WALL-E (2008)</item>
<item>Inglourious Basterds (2009)</item>
<item>Paths of Glory (1957)</item>
<item>Amelie (2001) (Fr.)</item>
<item>Double Indemnity (1944)</item>
<item>Alien (1979)</item>
<item>M (1931) (Ger.)</item>
<item>Terminator 2: Judgment Day (1991)</item>
<item>To Kill A Mockingbird (1962)</item>
<item>Saving Private Ryan (1998)</item>
<item>A Clockwork Orange (1971)</item>
<item>The Shining (1980)</item>
<item>The Treasure of the Sierra Madre (1948)</item>
<item>The Departed (2006)</item>
<item>The Third Man (1949)</item>
<item>The Pianist (2002)</item>
<item>The Lives of Others (2006, Germ.)</item>
<item>Chinatown (1974)</item>
<item>Spirited Away (2001, Jp.)</item>
<item>City Lights (1931)</item>
<item>Aliens (1986)</item>
<item>Eternal Sunshine of the Spotless Mind (2004)</item>
<item>L.A. Confidential (1997)</item>
<item>Requiem for a Dream (2000)</item>
<item>Das Boot (1981) (Ger.)</item>
<item>Reservoir Dogs (1992)</item>
<item>The Bridge On The River Kwai (1957)</item>
<item>Monty Python and the Holy Grail (1974)</item>
<item>Pan\'s Labyrinth (2006)</item>
<item>Raging Bull (1980)</item>
<item>All About Eve (1950)</item>
<item>The Maltese Falcon (1941)</item>
<item>Slumdog Millionaire (2008)</item>
<item>Singin\' In The Rain (1952)</item>
<item>District 9 (2009)</item>
<item>Rashomon (1950) (Jp.)</item>
<item>Modern Times (1936)</item>
<item>Some Like It Hot (1959)</item>
<item>The Prestige (2006)</item>
<item>Rebecca (1940)</item>
<item>Downfall (2004, Germ)</item>
<item>Gran Torino (2008)</item>
<item>Cinema Paradiso (1988)</item>
<item>Amadeus (1984)</item>
<item>The Apartment (1960)</item>
<item>2001: A Space Odyssey (1968)</item>
<item>The Elephant Man (1980)</item>
<item>Life is Beautiful (1997) (It.)</item>
<item>Metropolis (1927) (Ger.)</item>
<item>The Great Dictator (1940)</item>
<item>Once Upon a Time in America (1984)</item>
<item>Back to the Future (1985)</item>
<item>Full Metal Jacket (1987)</item>
<item>The Bicycle Thief (1948, It.)</item>
<item>Mr. Smith Goes to Washington (1939)</item>
<item>The Sting (1973)</item>
<item>The Great Escape (1963)</item>
<item>Braveheart (1995)</item>
</string-array>
</resources>
MovieAdapter.java
/**
* Another perfectly valid approach would be to create a Movie model class.
* get rid of the HashMap.
*/
//The MovieAdapter keeps track of selected movies
//Adapter separating data from its representation on the screen
public class MovieAdapter extends ArrayAdapter<String> {
//storing movie state data
//this state is transient
private HashMap<Integer,Boolean> movieCollection=new HashMap<Integer,Boolean>();
public MovieAdapter(Context context) {
super(context,R.layout.movie_item,android.R.id.text1,context.getResources().getStringArray(R.array.movies));
// TODO Auto-generated constructor stub
}
public void toggleMovie(int position){
if(!isInCollection(position)){
movieCollection.put(position, true);
}
else{
movieCollection.put(position, false);
}
}
public boolean isInCollection(int position){
return movieCollection.get(position) == Boolean.TRUE;
}
@Override
//returns the view needed for each item.
//cache and reuse item views via convertView for performance reasons
public View getView(int position,View convertView,ViewGroup parent){
View listitem=super.getView(position, convertView, parent);
CheckedTextView checkMark=null;
//getTag(). This method allows us to associate arbitrary data with a view.
ViewHolder holder=(ViewHolder)listitem.getTag();
//if the ViewHolder is present
if(holder!=null){
//eliminate extra calls to findViewById
//cache findViewById’s result in a ViewHolder object
checkMark=holder.checkMark;
}
else{
checkMark=(CheckedTextView)listitem.findViewById(android.R.id.text1);
holder=new ViewHolder(checkMark);
listitem.setTag(holder);
}
checkMark.setChecked(isInCollection(position));
return listitem;
}
//internal class hold the CheckedTextView we need
private class ViewHolder{
protected final CheckedTextView checkMark;
public ViewHolder(CheckedTextView checkMark){
this.checkMark=checkMark;
}
/**
* The ViewHolder pattern can help make your ListView faster and more efficient,
* and should always be considered
* when you expect to have more than a few items in the list.
*/
}
}
MyMovies.java
/**
* ListActivity takes care of many of the details of managing a ListView
* getListView(),onListItemClick()
*
*/
public class MyMovies extends ListActivity {
private MovieAdapter movieAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview=getListView();
//inflate this layout to receive a Button object
Button backToTop=(Button)getLayoutInflater().inflate(R.layout.list_footer, null);
backToTop.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(android.R.drawable.ic_menu_upload), null, null, null);
listview.addFooterView(backToTop,null,true);
this.movieAdapter=new MovieAdapter(this);
listview.setAdapter(movieAdapter);//provide the data source for the items the list will handle
listview.setItemsCanFocus(false);
}
@Override
protected void onListItemClick(ListView l,View v,int position,long id){
this.movieAdapter.toggleMovie(position);
this.movieAdapter.notifyDataSetChanged();
}
public void backToTop(View view) {
getListView().setSelection(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
(2) Adapter, the views for our ListView are bound to the data source we’ll use a static movies file, via our Adapter.
list is backed by data coming from an adapter.
When having to maintain dynamic data that can change in reaction to view events (or any other event), you’ll have to create your own adapter implementation that performs the following tasks:
If the data wrapped by the adapter changes, it must inform the view about these changes so it can redraw itself.
If the user interacts with the view in a way that’s supposed to update the data, we must inform the adapter about this and make the according changes to the data source.
(3)Header and footer views
must add all header and footer views before adding any data to your list (via ListView.setAdapter);
can’t rely on Adapter.getCount anymore
MyMovies.project
layout\acitivity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/title"
android:layout_width="fill_parent"
android:layout_height="45px"
android:scaleType="fitXY" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
layout\movie_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical">
<CheckedTextView
android:id="@android:id/text1"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_weight="0.9"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:paddingRight="6dip"
android:checkMark="?android:attr/listChoiceIndicatorMultiple" />
</LinearLayout>
layout\list_footer.xml
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:text="Back to top"
android:onClick="backToTop" />
android:onClick="backToTop" :look for a public method called backToTop defined in our activity, which takes a single View object as a parameter.
store them as an array resource in our application.
After all, application code is supposed to contain logic, not data.
values\movies.xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<string-array name="movies">
<item id="1">The Shawshank Redemption (1994)</item>
<item>The Godfather (1972)</item>
<item>The Godfather, Part II (1974)</item>
<item>The Good, the Bad, and the Ugly (1966) (It.)</item>
<item>Pulp Fiction (1994)</item>
<item>Schindler\'s List (1993)</item>
<item>12 Angry Men (1957)</item>
<item>One Flew Over The Cuckoo\'s Nest (1975)</item>
<item>The Dark Knight (2009)</item>
<item>Star Wars: Episode V: The Empire Strikes Back (1980)</item>
<item>Casablanca (1942)</item>
<item>Star Wars (1977)</item>
<item>The Lord of the Rings: The Return of the King (2003)</item>
<item>The Seven Samurai (1954) (Jp.)</item>
<item>GoodFellas (1990)</item>
<item>Rear Window (1954)</item>
<item>City of God (2002, Brazil/Fr.)</item>
<item>Raiders of the Lost Ark (1981)</item>
<item>Fight Club (1999)</item>
<item>The Lord of the Rings: The Fellowship of the Ring (2001)</item>
<item>Once Upon a Time in the West (1969) (It.)</item>
<item>The Usual Suspects (1995)</item>
<item>Psycho (1960)</item>
<item>The Silence of the Lambs (1991)</item>
<item>Sunset Boulevard (1950)</item>
<item>The Matrix (1999)</item>
<item>Memento (2000)</item>
<item>Dr. Strangelove or: How I Learned To Stop Worrying and Love the Bomb (1964)</item>
<item>North By Northwest (1959)</item>
<item>Se7en (1995)</item>
<item>It\'s A Wonderful Life (1946)</item>
<item>The Lord of the Rings: The Two Towers (2002)</item>
<item>Citizen Kane (1941)</item>
<item>Leon, aka The Professional (1994) (Fr.)</item>
<item>Apocalypse Now (1979)</item>
<item>American Beauty (1999)</item>
<item>American History X (1998)</item>
<item>Taxi Driver (1976)</item>
<item>Forrest Gump (1994)</item>
<item>Vertigo (1958)</item>
<item>Lawrence of Arabia (1962)</item>
<item>Up (2009)</item>
<item>WALL-E (2008)</item>
<item>Inglourious Basterds (2009)</item>
<item>Paths of Glory (1957)</item>
<item>Amelie (2001) (Fr.)</item>
<item>Double Indemnity (1944)</item>
<item>Alien (1979)</item>
<item>M (1931) (Ger.)</item>
<item>Terminator 2: Judgment Day (1991)</item>
<item>To Kill A Mockingbird (1962)</item>
<item>Saving Private Ryan (1998)</item>
<item>A Clockwork Orange (1971)</item>
<item>The Shining (1980)</item>
<item>The Treasure of the Sierra Madre (1948)</item>
<item>The Departed (2006)</item>
<item>The Third Man (1949)</item>
<item>The Pianist (2002)</item>
<item>The Lives of Others (2006, Germ.)</item>
<item>Chinatown (1974)</item>
<item>Spirited Away (2001, Jp.)</item>
<item>City Lights (1931)</item>
<item>Aliens (1986)</item>
<item>Eternal Sunshine of the Spotless Mind (2004)</item>
<item>L.A. Confidential (1997)</item>
<item>Requiem for a Dream (2000)</item>
<item>Das Boot (1981) (Ger.)</item>
<item>Reservoir Dogs (1992)</item>
<item>The Bridge On The River Kwai (1957)</item>
<item>Monty Python and the Holy Grail (1974)</item>
<item>Pan\'s Labyrinth (2006)</item>
<item>Raging Bull (1980)</item>
<item>All About Eve (1950)</item>
<item>The Maltese Falcon (1941)</item>
<item>Slumdog Millionaire (2008)</item>
<item>Singin\' In The Rain (1952)</item>
<item>District 9 (2009)</item>
<item>Rashomon (1950) (Jp.)</item>
<item>Modern Times (1936)</item>
<item>Some Like It Hot (1959)</item>
<item>The Prestige (2006)</item>
<item>Rebecca (1940)</item>
<item>Downfall (2004, Germ)</item>
<item>Gran Torino (2008)</item>
<item>Cinema Paradiso (1988)</item>
<item>Amadeus (1984)</item>
<item>The Apartment (1960)</item>
<item>2001: A Space Odyssey (1968)</item>
<item>The Elephant Man (1980)</item>
<item>Life is Beautiful (1997) (It.)</item>
<item>Metropolis (1927) (Ger.)</item>
<item>The Great Dictator (1940)</item>
<item>Once Upon a Time in America (1984)</item>
<item>Back to the Future (1985)</item>
<item>Full Metal Jacket (1987)</item>
<item>The Bicycle Thief (1948, It.)</item>
<item>Mr. Smith Goes to Washington (1939)</item>
<item>The Sting (1973)</item>
<item>The Great Escape (1963)</item>
<item>Braveheart (1995)</item>
</string-array>
</resources>
MovieAdapter.java
/**
* Another perfectly valid approach would be to create a Movie model class.
* get rid of the HashMap.
*/
//The MovieAdapter keeps track of selected movies
//Adapter separating data from its representation on the screen
public class MovieAdapter extends ArrayAdapter<String> {
//storing movie state data
//this state is transient
private HashMap<Integer,Boolean> movieCollection=new HashMap<Integer,Boolean>();
public MovieAdapter(Context context) {
super(context,R.layout.movie_item,android.R.id.text1,context.getResources().getStringArray(R.array.movies));
// TODO Auto-generated constructor stub
}
public void toggleMovie(int position){
if(!isInCollection(position)){
movieCollection.put(position, true);
}
else{
movieCollection.put(position, false);
}
}
public boolean isInCollection(int position){
return movieCollection.get(position) == Boolean.TRUE;
}
@Override
//returns the view needed for each item.
//cache and reuse item views via convertView for performance reasons
public View getView(int position,View convertView,ViewGroup parent){
View listitem=super.getView(position, convertView, parent);
CheckedTextView checkMark=null;
//getTag(). This method allows us to associate arbitrary data with a view.
ViewHolder holder=(ViewHolder)listitem.getTag();
//if the ViewHolder is present
if(holder!=null){
//eliminate extra calls to findViewById
//cache findViewById’s result in a ViewHolder object
checkMark=holder.checkMark;
}
else{
checkMark=(CheckedTextView)listitem.findViewById(android.R.id.text1);
holder=new ViewHolder(checkMark);
listitem.setTag(holder);
}
checkMark.setChecked(isInCollection(position));
return listitem;
}
//internal class hold the CheckedTextView we need
private class ViewHolder{
protected final CheckedTextView checkMark;
public ViewHolder(CheckedTextView checkMark){
this.checkMark=checkMark;
}
/**
* The ViewHolder pattern can help make your ListView faster and more efficient,
* and should always be considered
* when you expect to have more than a few items in the list.
*/
}
}
MyMovies.java
/**
* ListActivity takes care of many of the details of managing a ListView
* getListView(),onListItemClick()
*
*/
public class MyMovies extends ListActivity {
private MovieAdapter movieAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview=getListView();
//inflate this layout to receive a Button object
Button backToTop=(Button)getLayoutInflater().inflate(R.layout.list_footer, null);
backToTop.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(android.R.drawable.ic_menu_upload), null, null, null);
listview.addFooterView(backToTop,null,true);
this.movieAdapter=new MovieAdapter(this);
listview.setAdapter(movieAdapter);//provide the data source for the items the list will handle
listview.setItemsCanFocus(false);
}
@Override
protected void onListItemClick(ListView l,View v,int position,long id){
this.movieAdapter.toggleMovie(position);
this.movieAdapter.notifyDataSetChanged();
}
public void backToTop(View view) {
getListView().setSelection(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
相关文章推荐
- Android:Android ListActivity with a header or footer(为ListView添加header和footer)
- android tab with interacting map and list views
- Android HeaderAndFooterRecyclerView、ExRecyclerView、PullRefreshLoadRecyclerView、PowerfulRecyclerView
- HeaderAndFooterListViewAdapter
- java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter
- Android官方Training阅读笔记 ---- Managing the Activity Lifecycle(Stopping and Restarting an Activity) (三)
- [Android Bug] ListView中Header, Footer无法隐藏(gone)的问题
- java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter
- Butter Knife Field and method binding for Android views
- 2.10 Presenting and Managing Views with UIViewController
- java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter
- Android源码分析:HeaderViewListAdapter
- android in practice_create model、table class and sqlitehelper(MyMoviesDataBases project)
- Android关于页眉(header)和页脚(footer)的布局实例
- [android] cannot be cast to android.widget.HeaderViewListAdapter
- cannot be cast to android.widget.HeaderViewListAdapter
- Android中包含Header和Footer的无限ListView的实现
- Can a GridView have a footer and header just like ListView?
- Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint
- Android Material Design-Defining Shadows and Clipping Views(定义阴影和裁剪视图)-(四)