有一个下拉列表ExpandableListView,里面显示了国家和他们的景点。标题是国家/地区,当您单击国家/地区时,会打开一个包含景点的下拉列表。
如何为这些下拉元素本身制作自定义视图。
为下拉列表中的每个项目创建标记
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/img"
android:src="@drawable/bg"
app:civ_border_color="#FF000000"
android:layout_width="42dp"
android:layout_height="42dp"
android:scaleType="centerCrop" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<TextView
android:text=""
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txtTitle"
android:layout_weight="1"
android:gravity="left|center" />
<TextView
android:text=""
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txtHistory"
android:layout_weight="1"
android:singleLine="true" />
</LinearLayout>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/icon_star_outline_black"
android:id="@+id/btnfavorite"
android:background="@drawable/white_button"
android:focusable="false"
android:onClick="onFavoriteClick" />
</LinearLayout>
</LinearLayout>
数据库助手类
public class DBHeler extends SQLiteOpenHelper {
private static String DB_PATH;
private static final String DATABASE_NAME = "mydb.db";
private static final int DATABASE_VERSION = 1;
public SQLiteDatabase database;
private Context myContext;
public DBHeler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.myContext = context;
try {
//получаем путь до БД вместе с именем.
DB_PATH = myContext.getDatabasePath(DATABASE_NAME).toString();
createDataBase();
openDataBase();
} catch (IOException e) {
e.printStackTrace();
}
}
public Cursor getCategoryData() {
return this.getReadableDatabase().query(Contract.Entry.TABLE_COUNTRY, null, null, null, null, null, null);
}
public Cursor getSubCategoryData(long categoryID) {
return this.getReadableDatabase().query(Contract.Entry.TABLE_DOST, null, Contract.Entry._ID + " = "
+ categoryID, null, null, null, null);
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if (!dbExist) {
this.getReadableDatabase();
try {
copyDataBase();
}
catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try {
checkDB = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READONLY);
}
catch (SQLiteException e) {
// база не существует
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null;
}
private void copyDataBase() throws IOException {
InputStream myInput = myContext.getAssets().open(DATABASE_NAME);
String outFileName = DB_PATH;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
database = SQLiteDatabase.openDatabase(DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
}
@Override
public synchronized void close() {
if(database != null)
database.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
主要活动类
public class MainActivity extends AppCompatActivity {
ExpandableListView elvMain;
DBHeler db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DBHeler(this);
Cursor categoryData = db.getCategoryData();
startManagingCursor(categoryData);
String[] groupFrom = { Contract.Entry.COLUMN_NAME };
int[] groupTo = { android.R.id.text1 };
String[] childFrom = { Contract.Entry.COLUMN_NAME };
int[] childTo = { android.R.id.text1 };
SimpleCursorTreeAdapter sctAdapter = new MyAdapter(this, categoryData,
android.R.layout.simple_expandable_list_item_1, groupFrom,
groupTo, android.R.layout.simple_list_item_1, childFrom,
childTo);
elvMain = (ExpandableListView) findViewById(R.id.list);
elvMain.setAdapter(sctAdapter);
}
public class MyAdapter extends SimpleCursorTreeAdapter {
public MyAdapter(Context context, Cursor cursor, int groupLayout,
String[] groupFrom, int[] groupTo, int childLayout,
String[] childFrom, int[] childTo) {
super(context, cursor, groupLayout, groupFrom, groupTo,
childLayout, childFrom, childTo);
}
protected Cursor getChildrenCursor(Cursor groupCursor) {
int idColumn = groupCursor.getColumnIndex(Contract.Entry._ID);
return db.getSubCategoryData(groupCursor.getInt(idColumn));
}
}
}
Contract 类,描述字段和列名
public class Contract {
private Contract() {
};
public static final class Entry implements BaseColumns {
public final static String TABLE_DOST = "dost";
public final static String TABLE_COUNTRY = "country";
public final static String _ID = BaseColumns._ID;
public final static String COLUMN_NAME = "name";
public final static String COLUMN_OTHER = "other";
public final static String COLUMN_HISTORY = "history";
public final static String COLUMN_IMAGE = "image";
public final static String COLUMN_COUNTRY = "name";
public final static String COLUMN_COUNTRYID = "countryid";
public final static String COLUMN_FAVORITES = "favorites";
}
}


为了根据
SimpleCursorTreeAdapter以下方法为下拉列表中的项目制作自定义视图,您需要在适配器中覆盖它们:bindGroupView()- 对于自己的根项目bindChildView()- 用于列表下拉部分中自己类型的项目这些方法用于将标记中的小部件与游标数据绑定。
所需的标记本身是在创建适配器时通过构造函数指定的:
groupLayout- 像R.layout.item这样的链接用于标记根项childLayout- 链接到下拉标记此外,适配器本身,由于您不需要更改根项的外观,我们将限制自己使用嵌套项。在方法
bindChildView()中,我们在传递给适配器的标记中找到小部件,并将相应的数据从光标放入它们,也传递给方法并已经定位在所需的行上:在活动中创建适配器的实例时,我们为下拉列表项(构造函数的第六个参数)指定我们自己的而不是系统标记,例如,我们将其称为 my_item_list.xml:
如有必要,对根项执行相同的操作。