Slideable lists are a common UI layout effect on Android. So mastery of list controls is a sure thing; RecyclerView is one of the most important and complex list controls and will be explained in detail in another article.
I usually project development necessary framework
- The strongest network request Net on Android
- The strongest list on Android (including StateLayout) BRV
- Android’s strongest default page StateLayout
- JSON and long text log printing tool LogCat
- Supports asynchronous and global customization of the toast tool Tooltip
- Develop the debugging window tool DebugKit
- One line of code creates the transparent StatusBar StatusBar
The main control
- GridView
- GridLayout
- ListView
- Gallery (deprecated, replaced by HorizontalScrollView and ViewPager)
- ExpandableListView (Extensible list view)
- Spinner (drop-down view)
ListView
The main function is to reuse lists. Can handle a large number of list control combinations. Before Android21 was one of the most commonly used controls. After introducing RecyclerView control. It’s much more powerful than ListView and much more customizable.
But sometimes it’s more convenient to use ListView than RecyclerView. And there’s no official word that it should be scrapped.
The layout properties
XML attributes that can be used in layout files
attribute | describe |
---|---|
android:entries | References an array resource to form a list |
android:divider | Divider (Android: Divider =”@null” to remove dividers) |
android:dividerHeight | Splitter height (1DP height even if set to 0) |
android:footerDividersEnabled | Whether to open the foot parting line |
android:headerDividersEnabled | Whether the head divider will be opened |
Preview the item
tools:listitem="@layout/demo_item"
Copy the code
function
Head layout and foot layout
Add the layout
void addHeaderView (View v,
Object data,
boolean isSelectable)
void addHeaderView (View v)
void addFooterView (View v,
Object data,
boolean isSelectable)
void addFooterView (View v)
Copy the code
Delete layout
boolean removeHeaderView (View v)
boolean removeFooterView (View v)
Copy the code
The divider
// Whether the splitter is enabled
boolean areHeaderDividersEnabled (a)
boolean areFooterDividersEnabled (a)
// Whether to enable the splitter
void setHeaderDividersEnabled (boolean headerDividersEnabled)
void setFooterDividersEnabled (boolean footerDividersEnabled)
// By default, ListView does not cross bounds, so it has no effect by default
void setOverscrollFooter (Drawable footer)
void setOverscrollHeader (Drawable header)
Drawable getOverscrollHeader (a)
Drawable getOverscrollFooter (a)
Copy the code
Get the number of layouts
int getFooterViewsCount (a)
int getHeaderViewsCount (a)
Copy the code
Entry selection
void setSelection (int position)
Copy the code
Smooth scrolling
SmoothScroll represents smooth scrolling, By represents relative distance movement, and To remains unchanged only after being rolled To a specified position
// Relative scroll position
void smoothScrollToPosition (int position)
void smoothScrollByOffset (int offset)
Copy the code
It also inherits the scrollmethod from the AbsListView
// Cancel the fast scroll bar (fast scroll still has a small scroll bar that cannot be dragged)
void setSmoothScrollbarEnabled (boolean enabled)
boolean isSmoothScrollbarEnabled (a)
// Smooth scrolling while limiting the maximum scrolling range
void smoothScrollToPosition (int position,
int boundPosition) // Range unit: px
// Scroll pixels, and you can control the scrolling duration
void smoothScrollBy (intdistanceint duration)
// The specified scroll position is offset by some distance up
void smoothScrollToPositionFromTop (int position,
int offset) // Offset distance
// Add control to scroll duration
void smoothScrollToPositionFromTop (int position,
int offset,
int duration)
Copy the code
rolling
void scrollListBy (int y)
Copy the code
The adapter
Learning adapters distinguish between methods:
-
Methods used to override. This type of method is called to the ListView (the adapter passes the ListView through setAdapter())
-
The method used to invoke. Exposed to the user to control the Item
The ListView adopts the MVC architecture, and the View and Data are controlled by an Adapter. The Adapter used by ListView is the ListAdapter. Set using the setAdapter() method.
The most basic adapter, ListAdapter, is an interface. There are many ways to implement it. An abstract adapter that inherits the ListAdapter is provided for convenience
Adapter inheritance relationship
- Adapter
- ListAdapter
- BaseAdapter
- SimpleAdapter
- ArrayAdapter
- CursorAdapter
- ResourceCursorADapter
- SimpleCursorAdapter
- WrapperListAdapter
- HeaderViewListAdapter
- BaseAdapter
- SpinnerAdapter
- ListAdapter
The above adapter works with ListView and GridView and Spinner.
ListAdapter
ListAdapter is an interface and is generally not used directly because it is not necessary to override all methods. Subclasses are generally used.
// Whether to enable item. If fasle is not enabled, item is unselectable and unclickable
boolean isEnabled(int position);
// You can see that there is no position argument. So if fasle is returned, all items are disabled
public boolean areAllItemsEnabled(a);
Copy the code
A method that inherits from a parent class
int getCount (a) // Determine the number of items in the ListView
Object getItem (int position) // Get item data. The value returned here will be used in the ListView
long getItemId (int position) // Get the item ID. The value returned here will be used in the ListView
// Return the Item type. Whether the type is the same determines whether to reuse Item
int getItemViewType (int position)
// Returns the contents of the Item view
View getView (intPosition, // View convertView, // ViewGroup parent) / / the parent container
// Return the number of Item types
int getViewTypeCount (a)
// Whether the id is unique
boolean hasStableIds (a)
boolean isEmpty (a) // Whether it is empty
void registerDataSetObserver (DataSetObserver observer) // Register the data observer
void unregisterDataSetObserver (DataSetObserver observer) // Cancel the data observer
Copy the code
Whether or not the only
HasStableIds () is a method that checks whether the ID is valid. Returns true valid false invalid.
- Valid case will pass
getItemId()
Returns the id value to determine if the items are the same - If it is invalid, the position of the item is used as the ID by default
BaseAdapter
First I’ll talk about the most common adapter, BaseAdapter.
Features:
-
ListView supports highly customized items
-
You need to rewrite the adapter yourself to use it
Overriding methods
final String[] title = {"User"."Home page"."Settings"."About"."Feedback"};
// This is an anonymous class
mListView.setAdapter(new BaseAdapter() {
/** * Controls the number of items in the ListView *@return* /
@Override
public int getCount(a) {
return title.length;
}
/** * Controls the Object data returned by some methods of the ListView, such as the ListView getItemAtPosition() method. The location index yields the data Object, the Object returned by this method * *@param position
* @return* /
@Override
public Object getItem(int position) {
return null;
}
/** * this method is called back every time you click on item. The ListView getItemIdAtPosition() method gets the item ID * *@param position
* @return* /
@Override
public long getItemId(int position) {
return 0;
}
/** * Controls the display of the ListView Item view **@paramPosition Indicates the current view position *@paramConvertView Cached view. Used to reuse item *@paramParent Parent container layout *@return* /
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(MainActivity.this, R.layout.item_list, null);
// Make changes based on incoming data
TextView text = ButterKnife.findById(view, R.id.text);
text.setText(title[position]);
returnview; }});Copy the code
Add controls to the main layout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.liangjingkanji.listview.MainActivity">
<ListView
android:id="@+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
Copy the code
Notice whether parent is enabled when the Inflate Item view is view.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Copy the code
I’m not going to write out the layout file. Redundant code affects readability.
This section describes the methods that BaseAdapter adds to the parent ListAdapter class. None of this is necessary
// Check whether the adapter has item
boolean isEmpty (a)
// **DropDownView** and other methods are overridden SpinnerAdapter. So we'll talk more about that when we talk about Spinner. ListView and GridView are not useful
View getDropDownView (int position,
View convertView,
ViewGroup parent)
boolean hasStableIds (a)
void notifyDataSetChanged (a) // Notify ListView of local updates if data changes
void notifyDataSetInvalidated (a) // If the data changes, notify ListView of the entire update
Copy the code
ArrayAdapter
ArrayAdapter, a subclass of BaseAdapter, is further encapsulated to quickly implement the simplest list of strings (while limiting the data to a single string). Note that this is not an abstract class. You can create objects directly.
Features:
- All you need is a constructor to create a ListView
- Customization is weak, and ListView data can only be strings.
When creating an ArrayAdapter, specify the generic ArrayAdapter
. Generics determine the data types accepted by the constructor
A constructor
ArrayAdapter (Context context, / / context
int resource) // Layout id. Only the layout whose root layout is TextView is supported
ArrayAdapter (Context context,
int resource, // This constructor supports arbitrary layouts
int textViewResourceId) // Specify a Textview ID to set the data.
ArrayAdapter (Context context,
int resource,
T[] objects) // Add data directly to the constructor, which must be an array of strings
ArrayAdapter (Context context,
int resource,
int textViewResourceId,
T[] objects) / / same as above
ArrayAdapter (Context context,
int resource,
List<T> objects)// Add data set, again must be a string
ArrayAdapter (Context context,
int resource,
int textViewResourceId, / / same as above
List<T> objects) // Add data set
Copy the code
The sample
String[] array = {"User"."Home page"."Settings"."About"."Feedback"};
// Android.r.layout. simple_list_item_1 is a TextView layout file provided by the system. You can click open to see the source code.
listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array));
Copy the code
Doesn’t look like it’s easy to implement the ListView.
Pay attention to
-
The ListView has already been reused within the ArrayAdapter
-
The data passed in must be a string. The source code has been judged
-
The ArrayAdapter does not reuse a ViewHolder.
methods
// Add data
void add (T object)
// Add more data
void addAll (T... items)
// Add collection
void addAll (Collection<? extends T> collection)
// Delete all data
void clear (a)
// Delete the specified data
void remove (T object)
// Insert data in the corresponding position
void insert (T object,
int index)
// The default is true. So you call the notifyOnChange method every time you modify data. Multiple calls affect efficiency (frequently refreshing the UI). You can set false with this method. You then call methods such as notifyChange yourself to update the UI of the Item.
void setNotifyOnChange (boolean notifyOnChange)
// This is a static method to create a ListView directly. Simple and straightforward
ArrayAdapter<CharSequence> createFromResource (Context context,
intTextArrayResId, // Text dataint textViewResId) // Text control ID
// Get the context passed in
Context getContext (a)
// Get the index from the data
int getPosition (T item)
Copy the code
Here are two more methods to override the filter Item functionality that supports ListView
// Filter, such as association filter for contacts
Filter getFilter (a)
// Use standard comparator sort operations on data
void sort (Comparator<? super T> comparator)
Copy the code
SimpleAdapter
SimpleAdapter is the most complex of the three, but data populates ListView items conveniently. Similarly, non-abstract classes can be used to create objects directly.
Again, the constructor is introduced first
SimpleAdapter (Context context, List<? extends Map<String, ? >> data,Each Item corresponds to a set of maps
int resource, // Item layout
String[] from, // The Map collection is unordered. So you need a key array to control the order
int[] to) // The data is populated with the View ID corresponding to the array
Copy the code
The sample
Create a ListView as the data
// List collection stores Map collection representative data
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> map = new HashMap<>();
map.put("icon", R.mipmap.ic_launcher);
map.put("name"."Settings");
Map<String, Object> map2 = new HashMap<>();
map2.put("icon", R.mipmap.ic_launcher);
map2.put("name"."About");
list.add(map);
list.add(map2);
// The value of the String data is the key in the Map collection, corresponding to the control ID in the int array. Populate the corresponding ID control with the value corresponding to the key
listView.setAdapter(new SimpleAdapter(this,list, R.layout.list_item, new String[]{"icon"."name"}, new int[]{R.id.icon, R.id.name}));
Copy the code
SimpleAdapter can only support TextView and Checkable and ImageView property values, if not the three will throw syntax exception messages.
If the ViewBinder interface is passed in, the data population can be handled manually within the callback method
SimpleAdapter.ViewBinder getViewBinder (a)
void setViewBinder (SimpleAdapter.ViewBinder viewBinder)
Copy the code
WrapperListAdapter
As mentioned earlier, this adapter inherits from ListAdapter just like BaseAdapter. But this is the interface. There is only one method inside:
// Return the adapter object. Equivalent getAdapter
ListAdapter getWrappedAdapter (a)
Copy the code
HeaderViewListAdapter
ListAdapter that supports both head and foot layouts
A constructor
// Add two sets of header and foot layouts plus a normal ListAdapter
HeaderViewListAdapter (ArrayList<ListView.FixedViewInfo> headerViewInfos,
ArrayList<ListView.FixedViewInfo> footerViewInfos,
ListAdapter adapter)
Copy the code
AddHeaderView and addFootView are implemented by wrapping the existing adapter into a HeaderViewListAdapter.
FixedViewInfo
public class FixedViewInfo {
/ / view
public View view;
/ / data
public Object data;
// Whether to select. Selectable state
public boolean isSelectable;
}
Copy the code
Click on the event
// Normal click events
void setOnClickListener (View.OnClickListener l)
// item click event
void setOnItemClickListener (AdapterView.OnItemClickListener listener)
// item long click event
void setOnItemLongClickListener (AdapterView.OnItemLongClickListener listener)
// item selects the event
void setOnItemSelectedListener (AdapterView.OnItemSelectedListener listener)
Copy the code
Multiple entries
Often the items in a list are not exactly the same, and need to be mixed with different types of items.
Here are two methods: getViewTypeCount and getItemViewType
Two methods are implemented by default
We implement multiple entries by overriding these two methods in BaseAdapter
Tip: convertView will not work if you use position directly in the getView method. This will result in a distorted view.
Memory optimization
When you swipe the screen, items that the ListView disappears from the screen are destroyed, and new items that appear on the screen are created. Quick swiping of a large number of items that display too much content will cause memory to be recycled faster than the creation of item objects, causing oom memory to run out. To avoid this, ListView needs to be optimized for memory overcommitment.
The reuse entry
The getView() method is called every time an item is displayed on the screen. If a View object is created in this method every time, the OOM memory will run out, so reuse this View object. The getView method already caches this object the convertView parameter, so you just call it.
/** * returns the item display, which is a View object *@paramPosition The position of the entry *@paramConvertView entries reuse objects *@param parent
* @return* /
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
// If convertView is not empty, reuse it
if (convertView == null) {
view = View.inflate(MainActivity.this, R.layout.list_item, null);
}else {
view = convertView;
}
TextView text = (TextView) view.findViewById(R.id.text);
text.setText("Current entry" + position);
return view;
}
Copy the code
ViewHolder
FindViewById traverses the entire layout each time, which can affect the efficiency of the program, so you can create a ViewHolder class to store control references. Each Item then accesses the ViewHolder;
Key method setTag()
// Define the ViewHolder static class outside
static class ViewHolder
{
public ImageView img;
public TextView title;
public TextView info;
}
// Then override getView
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.list_item, null);
holder.img = (ImageView)item.findViewById(R.id.img)
holder.title = (TextView)item.findViewById(R.id.title);
holder.info = (TextView)item.findViewById(R.id.info);
convertView.setTag(holder);
}else
{
holder = (ViewHolder)convertView.getTag();
}
holder.img.setImageResource(R.drawable.ic_launcher);
holder.title.setText("Hello");
holder.info.setText("World");
}
return convertView;
}
Copy the code
RecyclerView is mandatory to use ViewHolder;
Select the schema
ListView actually supports multiple selection mode Settings
/** * No mode is selected */
public static final int CHOICE_MODE_NONE = 0;
/** * Single mode */
public static final int CHOICE_MODE_SINGLE = 1;
/** * Multi-select mode */
public static final int CHOICE_MODE_MULTIPLE = 2;
/** * The list allows multiple choices in a modal selection mode */
public static final int CHOICE_MODE_MULTIPLE_MODAL = 3;
Copy the code
Select mode by setting layout properties
android:choiceMode
Copy the code
Constant | Value | Description |
---|---|---|
multipleChoice | 2 | Multiselect mode |
multipleChoiceModal | 3 | Multiple selection mode for blocking click events |
none | 0 | The selected mode |
singleChoice | 1 | Radio mode |
Methods for selecting modes are in the AbsListView abstract class
boolean isItemChecked (int position)
// Check whether the item at the specified position is selected
void setItemChecked (int position,
boolean value)
// Set the item check
int getCheckedItemCount (a)
// The number of items selected
long[] getCheckedItemIds (a)
// only valid if the mode is not optional and (hasStableIds() == true)
int getCheckedItemPosition (a)
// Index of selected position (only available in radio mode)
SparseBooleanArray getCheckedItemPositions (a)
// Get the positions of all selected items
void clearChoices (a)
// Clear all selected items
int getChoiceMode (a)
// Select the mode
void setChoiceMode (int choiceMode)
// Set the selection mode
void setMultiChoiceModeListener (AbsListView.MultiChoiceModeListener listener)
// Multi-select listener
Copy the code
The selection mode must meet the following requirements:
-
Set selection mode (radio mode by default)
-
Item has no child controls to intercept focus
android:focusable="false" Copy the code
Multiple selection mode for blocking click events
There are two ways to enter the multiple selection mode in this mode:
- Long press the item
- By function call
setItemChecked
GridView
Translation means “grid view”. The difference with ListView is the grid list.
Note, however, that the GridView is not a horizontal sliding layout, but a ListView that increases the number of columns. Horizontal sliding layout can be used HorizontalScrollView and RecyclerView GridLayoutManager layout
The GridView is compatible with all of the ListView’s adapters.
The layout properties
Each property has a corresponding method. Detailed introduction to see the method.
attribute | describe |
---|---|
android:columnWidth | Column width (invalid by default) needs to be used in conjunction with stretch mode |
android:numColumns | Number of columns (default 1) |
android:stretchMode | Stretching mode |
android:horizontalSpacing | Horizontal spacing |
android:verticalSpacing | The vertical distance between |
android:gravity | alignment |
The sample
Use the same as ListView. Support for all of the ListAdapter adapters discussed earlier;
mList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, title));
mList.setNumColumns(2); // Set the number of columns. Default 1. The same as ListView
Copy the code
Column width and spacing
A GridView is like a grid list. It is very important to learn how to arrange the grid.
The figure above illustrates the GridView’s column width and horizontal and vertical spacing
The width of the grid
// The width of the grid. Pixel unit
int getColumnWidth (a)
void setColumnWidth (int columnWidth)
Copy the code
Tip: If you set a fixed size in the layout of an item, this will result in clipping.
Stretching mode
Stretch mode is what I think is the most important and most difficult part of GridView to understand. Pay attention to understand my analysis
// Set the stretch mode
void setStretchMode (int stretchMode)
Copy the code
Four stretching modes are supported
-
NO_STRETCH
No stretching, size control yourself. The grid width must be set in this mode otherwise nothing will be displayed, right
-
STRETCH_COLUMN_WIDTH
By default, column width is determined by screen stretching. So the setColumnWidth described earlier is invalid. The grid content is scaled according to the screen size
-
STRETCH_SPACING
The mode must specify the column width or it will not display, and the self-specified spacing (both horizontal and vertical) is invalid
-
STRETCH_SPACING_UNIFORM
In this mode, the following widths and spacing are valid values, and the horizontal leftmost spacing is also available.
However, since all values are valid, the effect of screen distribution cannot be achieved
Specify grid width (setColumnWidth) for all modes except STRETCH_COLUMN_WIDTH.
Conclusion:
- Stretch spacing or column width cannot be set.
- If the column width and spacing are not in stretch mode, it cannot be evenly distributed
- If you’re not stretching the column width you have to specify the column width or you don’t display the content.
spacing
// Set the horizontal interval
int getHorizontalSpacing (a)
void setHorizontalSpacing (int horizontalSpacing)
// Set the vertical interval
void setVerticalSpacing (int verticalSpacing)
int getVerticalSpacing (a)
Copy the code
The number of columns
void setNumColumns (int numColumns)
int getNumColumns (a)
Copy the code
alignment
int getGravity (a)
void setGravity (int gravity)
Copy the code
Methods to introduce
// Return the adapter
ListAdapter getAdapter (a)
Copy the code
Nested list
Here we introduce nesting between GridViews and ListViews or between two types of identical lists.
List nested problems fall into two categories:
- Display incomplete
- Nested lists cannot slide
The first kind of
If there is a nested list a highly to wrap_content | match_parent list when they found, according to list cannot be nested but this situation will happen if the height of the fixed, but many data are not fixed but by the number of dynamic load data.
Use custom onMeasure methods to give nested ListViews an unlimited maximum height
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
Copy the code
Integer has a maximum of 32 bits, shifted two to the right because the first two bits represent the schema in MeasureSpec
Private static final int MODE_SHIFT = 30;
// Int is 32 bits, moved 30 bits to the left. This attribute represents the mask value, and is used to “&” size and mode to obtain the corresponding value. private static final int MODE_MASK = 0x3 << MODE_SHIFT;
// Move 30 bits to the left, the value is 00… Public static final int UNSPECIFIED = 0 << MODE_SHIFT;
// Move 30 bits to the left, the value is 01… Public static final int EXACTLY = 1 << MODE_SHIFT;
// Move 30 bits to the left, the value is 10… Public static final int AT_MOST = 2 << MODE_SHIFT;
If you don’t want to override the ListView, dynamically set the ListView height by the number of items in the ListView
private void setListViewHeight(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0.0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
Copy the code
Or you can set layoutParams for each View object in the getView method
The second,
The two approaches described above only address the problem of listViews not being displayed when nested. But if you have a nested ListView and you have a sliding ListView, you need to do something else.
In fact, Google has taken this problem into account and provided a method that works directly
ViewCompat.setNestedScrollingEnabled(mList,true); // Api21 can be used directly with View instead of ViewCompat
Copy the code
The second case does not occur with NestedScrollView and nested ListViews or GridViews in ScrollView, but incomplete displays can occur. Same solution.
The solution to the second method of nesting GridView and ListView in RecyclerView is invalid.
ExpandableListView
ExpandableListView is a ListView that supports group expansion.
There are two main parts: groups and sublists
Attributes
Indicator icon
android:groupIndicator
android:childIndicator
Copy the code
Indicator interval
android:indicatorEnd
android:indicatorLeft
android:indicatorRight
android:indicatorStart
android:childIndicatorEnd
android:childIndicatorLeft
android:childIndicatorRight
android:childIndicatorStart
Copy the code
The indicator icon will overlap with the contents of your getView() view. A padding is recommended for item
Sublist splitter
android:childDivider
Copy the code
The divider can be an image or a color. But it’s a full screen splitter at 1DP height anyway. The adapter isChildSelectable() method must return true.
Remove the default indicator and divider
android:divider="@null"
android:groupIndicator="@null"
Copy the code
ExpandableListAdapter
The ExpandaleListAdapter belongs to an interface. In general, the subclasses are used directly.
abstract boolean areAllItemsEnabled(a)
// This method is used by the adapter to return view data
abstract Object getChild(int groupPosition, int childPosition)
// Sublist item ID
abstract long getChildId(int groupPosition, int childPosition)
// Sublist item view
abstract View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent)
/ / child list
abstract int getChildrenCount(int groupPosition)
abstract long getCombinedChildId(long groupId, long childId)
abstract long getCombinedGroupId(long groupId)
/ / set of objects
abstract Object getGroup(int groupPosition)
/ / group number
abstract int getGroupCount(a)
/ / group id
abstract long getGroupId(int groupPosition)
// Return to the group view
abstract View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
// If id is stable, this method is equivalent to ListView
abstract boolean hasStableIds(a)
// Whether the sublist is optional
abstract boolean isChildSelectable(int groupPosition, int childPosition)
abstract boolean isEmpty(a)
// Group collapse callback
abstract void onGroupCollapsed(int groupPosition)
// Group expansion callback
abstract void onGroupExpanded(int groupPosition)
Copy the code
BaseExpandableListAdapter
Similar to BaseAdapter, the methods that need to be implemented have been described above. The following is a straightforward example;
public class CustomExpandableListAdapter extends BaseExpandableListAdapter {
private Context mContext;
private List<String> mGroupData;
private List<ArrayList<String>> mChildData;
public CustomExpandableListAdapter(Context context, List<String> groupData, List<ArrayList<String>> childData) {
mContext = context;
mGroupData = groupData;
mChildData = childData;
}
@Override public int getGroupCount(a) {
return mGroupData.size();
}
@Override public int getChildrenCount(int i) {
return mChildData.size();
}
@Override public Object getGroup(int i) {
return mGroupData.get(i);
}
@Override public Object getChild(int i, int i1) {
return mChildData.get(i).get(i1);
}
@Override public long getGroupId(int i) {
return i;
}
@Override public long getChildId(int i, int i1) {
return i+i1;
}
@Override public boolean hasStableIds(a) {
return true;
}
@Override public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
if(view == null) {
}
View groupView = LayoutInflater.from(mContext).inflate(R.layout.item_group_text, viewGroup, false);
TextView tvTitle = ButterKnife.findById(groupView, R.id.tv_title);
tvTitle.setText(mGroupData.get(i));
return groupView;
}
@Override public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) {
View childView = LayoutInflater.from(mContext).inflate(R.layout.item_group_text, viewGroup, false);
TextView tvTitle = ButterKnife.findById(childView, R.id.tv_title);
tvTitle.setText(mChildData.get(i).get(i1));
return childView;
}
@Override public boolean isChildSelectable(int i, int i1) {
return true; }}Copy the code
SimpleExpandableListAdapter
SimpleExpandableListAdapter and SimpleAdapter almost does not belong to the abstract class, you just need to use the constructor to create instances.
SimpleExpandableListAdapter (Context context, List<? extends Map<String, ? >> groupData,/ / data
int groupLayout, // Group view layout
String[] groupFrom, / / data key
int[] groupTo, // Layout control IDList<? extends List<? extends Map<String, ? >>> childData,int childLayout, // Sublist view
String[] childFrom,
int[] childTo) SimpleExpandableListAdapter (Context context, List<? extends Map<String, ? >> groupData,int expandedGroupLayout, // Rent the layout
int collapsedGroupLayout, // Group folding layout
String[] groupFrom,
int[] groupTo, List<? extends List<? extends Map<String, ? >>> childData,int childLayout,
String[] childFrom,
int[] childTo) SimpleExpandableListAdapter (Context context, List<? extends Map<String, ? >> groupData,int expandedGroupLayout,
int collapsedGroupLayout,
String[] groupFrom,
int[] groupTo, List<? extends List<? extends Map<String, ? >>> childData,int childLayout,
int lastChildLayout, // Rent the view of the last sublist
String[] childFrom,
int[] childTo)
Copy the code
From a constructor can see SimpleExpandableListAdapter also supports two kinds of fixed kinds of layout. Note that the groupTo/childTo control IDS for multi-type layouts must still be included.
The listener
Sublist click events
void setOnChildClickListener (ExpandableListView.OnChildClickListener onChildClickListener)
Copy the code
Group click event
void setOnGroupClickListener (ExpandableListView.OnGroupClickListener onGroupClickListener)
Copy the code
Group shrink and expand events
void setOnGroupCollapseListener (ExpandableListView.OnGroupCollapseListener onGroupCollapseListener)
void setOnGroupExpandListener (ExpandableListView.OnGroupExpandListener onGroupExpandListener)
Copy the code
Unfolding and shrinking a group simply requires returning true in the callback of the group click event
mExpand.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView expandableListView, View view, int i,
long l) {
return true; }});Copy the code
Spinner
Although Spinner is a container layout, it does not support child controls. Because it inherits AdapterView;
Simple implementation
Create controls in the layout
<Spinner
android:id="@+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/entries"
/>
Copy the code
Values /strings creates an array entity
<resources>
<string-array name="entries">
<item>Mercury</item>
<item>Venus</item>
<item>Earth</item>
<item>Mars</item>
<item>Jupiter</item>
<item>Saturn</item>
<item>Uranus</item>
<item>Neptune</item>
</string-array>
</resources>
Copy the code
Attributes
// Horizontal and vertical offset. Only vertical is valid
android:dropDownHorizontalOffset
android:dropDownVerticalOffset
android:dropDownWidth // Drop down the popover width
android:dropDownSelector // Drop down the color picker
android:gravity
android:popupBackground // Drop down popover background color
android:spinnerMode // dialog box/dropdown popover
android:prompt // The title of the dialog mode. Note that string is referenced
Copy the code
Choose listening
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<? > parent, View view,int position, long id) {}@Override public void onNothingSelected(AdapterView
parent) {}});Copy the code
If you just want to use drop-down lists you can look at ListPopupWindow; Simple drop down list, provide attachment function and custom width and height;