Android: 只显示 ListView 中的最后一项实现 BaseAdapter
Android: Only last item in ListView is displayed implementing BaseAdapter
首先介绍一些背景信息:
在我的 android 应用程序中,我在 SQLite 数据库中有一些与物理密钥相关的信息。此信息包括颁发钥匙的 'service provider' 的姓名,以及钥匙用于哪扇门的描述和那扇门的 ID。我想要做的是在 ListView
元素的一行中显示每个 'key' 的所有信息,并在行末尾有一个删除按钮,可用于从中删除该信息数据库。
现在的问题是,当我尝试这个时,activity 中显示的唯一条目是最后一个条目,而其他条目本来应该是空的 space。请在此处查看屏幕截图:(http://i.stack.imgur.com/8C15B.png)
我用红色标出的 space 是前 3 个条目所在的空白 space。我查了一下,对这类问题的所有回答都是他们将数据输入数组列表的方式有问题,但我已经测试过,数组列表正确地填充了所有 4 个条目。我只是不知道为什么他们没有显示,而且我对 android 还比较陌生,所以任何帮助将不胜感激!
这是相关文件中的代码:
MainActivity.java: (完成我的调试打印语句。这些打印语句都显示在 ArrayList 中有 4 个不同的条目,将它们添加到 addKeyItems() 方法的 do while 循环中。)
public class MainActivity extends AppCompatActivity {
private ListView mKeyListView;
//for the nav drawer
private ListView mDrawerList;
private ArrayAdapter<String> mAdapter;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private String mActivityTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(SaveSharedPreference.getUserName(MainActivity.this).length()==0){
//log in
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}else{
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.display_username);
String name = SaveSharedPreference.getUserName(this);
textView.setText("Logged in: " + name);
//navigation drawer
mDrawerList = (ListView)findViewById(R.id.navList);
System.out.println(mDrawerList);
addDrawerItems();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
mActivityTitle = getTitle().toString();
setupDrawer();
//main content
mKeyListView = (ListView) findViewById(R.id.keyList);
addKeyItems();
}
}
private void addKeyItems(){
DbAccess dba = new DbAccess();
Cursor cursor = dba.getKeys(getApplicationContext());
if(cursor.moveToFirst()) {
List<KeyModel> myKeyModelList = new ArrayList<KeyModel>();
int position = 0;
do {
KeyModel key = new KeyModel();
key.setReaderId(cursor.getLong(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry._ID)));
key.setSpName(cursor.getString(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry.SP_NAME)));
key.setReaderDesc(cursor.getString(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry.READER_DESCRIPTION)));
myKeyModelList.add(key);
System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
position++;
} while (cursor.moveToNext());
for(int i = 0; i < myKeyModelList.size(); i++){
KeyModel test = myKeyModelList.get(i);
System.out.println(test.spName+ " "+ test.readerDesc);
}
//create adapter with the arraylist of keys
MyListAdapter mKeyAdapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.key_list_entry, (ViewGroup)findViewById(R.id.main_linear_layout)));
mKeyAdapter.setModel(myKeyModelList);
//set the adapter to the ListView
mKeyListView.setAdapter(mKeyAdapter);
} else{
System.out.println("No keys");
}
}
private class KeyModel{
long readerId;
String spName;
String readerDesc;
public long getReaderId() {
return readerId;
}
public void setReaderId(long readerId) {
this.readerId = readerId;
}
public String getSpName() {
return spName;
}
public void setSpName(String spName) {
this.spName = spName;
}
public String getReaderDesc() {
return readerDesc;
}
public void setReaderDesc(String readerDesc) {
this.readerDesc = readerDesc;
}
View.OnClickListener listener = new View.OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, spName, Toast.LENGTH_SHORT).show();
//do other things to delete this once all items are displaying correctly
}
};
}
private class MyListAdapter extends BaseAdapter{
View renderer;
List<KeyModel> keys;
// call this one and pass it layoutInflater.inflate(R.layout.key_list_entry)
public MyListAdapter(View renderer) {
this.renderer = renderer;
}
// whenever you need to set the list of keys just use this method.
// call it when you have the data ready and want to display it
public void setModel(List<KeyModel> keys){
this.keys = keys;
System.out.println(keys.size());
notifyDataSetChanged();
}
@Override
public int getCount() {
if(keys!=null){
return keys.size();
}
return 0;
}
@Override
public Object getItem(int position) {
if(keys!=null){
return keys.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
if(keys!=null){
System.out.println("item id "+ position);
return position;
}
System.out.println(-1);
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null){
convertView = renderer;
}
KeyModel key = keys.get(position);
System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
TextView rIdView = (TextView)convertView.findViewById(R.id.key_id);
rIdView.setText(Long.toString(key.readerId));
TextView spNameView = (TextView)convertView.findViewById(R.id.sp_name);
spNameView.setText(key.spName);
TextView readerDescView = (TextView)convertView.findViewById(R.id.reader_desc);
readerDescView.setText(key.readerDesc);
Button button = (Button)convertView.findViewById(R.id.delete_keyButton);
button.setOnClickListener(key.listener);
convertView.setVisibility(View.VISIBLE);
return convertView;
}
}
activity_main.xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The first child in the layout is for the main Activity UI-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/main_list_layout">
<TextView
android:id="@+id/display_username"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/keyList"
android:orientation="vertical" >
</ListView>
</LinearLayout>
<!-- Side navigation drawer UI -->
<ListView
android:id="@+id/navList"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#424242"/>
key_list_entry.xml:
<?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:id="@+id/main_linear_layout">
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.05">
<TextView
android:id="@+id/key_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.35">
<TextView
android:id="@+id/sp_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.35">
<TextView
android:id="@+id/reader_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.25">
<Button
android:id="@+id/delete_keyButton" style="?android:textAppearanceSmall"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/delete" android:textStyle="bold" />
</RelativeLayout>
在MyListAdapter的GetView方法中的print语句中:System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
它在调用该方法时正确打印列表中的 4 个元素中的每一个:
这是输出:
09-28 20:23:47.731 20156-20156/com.blah.blah I/System.out﹕ 0 Company1 Front door
09-28 20:23:47.745 20156-20156/com.blah.blah I/System.out﹕ 1 Company1 Back Door
09-28 20:23:47.745 20156-20156/com.blah.blah I/System.out﹕ 2 Occipitech Front door
09-28 20:23:47.746 20156-20156/com.blah.blah I/System.out﹕ 3 Occipitech Garage door
再次感谢您的帮助!这是我的第一个 post,所以如果我做错了什么或者您需要更多信息,请告诉我。我认为问题可能出在我对 BaseAdapter 的实现中,因为列表本身包含所有正确的信息。
不能在所有列表项中使用单一视图。列表中显示的所有行必须是根据传递的数据循环的唯一视图。
所以改变..
if(convertView==null){
convertView = renderer;
}
至
if(convertView==null){
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.key_list_entry);
}
首先介绍一些背景信息:
在我的 android 应用程序中,我在 SQLite 数据库中有一些与物理密钥相关的信息。此信息包括颁发钥匙的 'service provider' 的姓名,以及钥匙用于哪扇门的描述和那扇门的 ID。我想要做的是在 ListView
元素的一行中显示每个 'key' 的所有信息,并在行末尾有一个删除按钮,可用于从中删除该信息数据库。
现在的问题是,当我尝试这个时,activity 中显示的唯一条目是最后一个条目,而其他条目本来应该是空的 space。请在此处查看屏幕截图:(http://i.stack.imgur.com/8C15B.png)
我用红色标出的 space 是前 3 个条目所在的空白 space。我查了一下,对这类问题的所有回答都是他们将数据输入数组列表的方式有问题,但我已经测试过,数组列表正确地填充了所有 4 个条目。我只是不知道为什么他们没有显示,而且我对 android 还比较陌生,所以任何帮助将不胜感激!
这是相关文件中的代码: MainActivity.java: (完成我的调试打印语句。这些打印语句都显示在 ArrayList 中有 4 个不同的条目,将它们添加到 addKeyItems() 方法的 do while 循环中。)
public class MainActivity extends AppCompatActivity {
private ListView mKeyListView;
//for the nav drawer
private ListView mDrawerList;
private ArrayAdapter<String> mAdapter;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private String mActivityTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(SaveSharedPreference.getUserName(MainActivity.this).length()==0){
//log in
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}else{
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.display_username);
String name = SaveSharedPreference.getUserName(this);
textView.setText("Logged in: " + name);
//navigation drawer
mDrawerList = (ListView)findViewById(R.id.navList);
System.out.println(mDrawerList);
addDrawerItems();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
mActivityTitle = getTitle().toString();
setupDrawer();
//main content
mKeyListView = (ListView) findViewById(R.id.keyList);
addKeyItems();
}
}
private void addKeyItems(){
DbAccess dba = new DbAccess();
Cursor cursor = dba.getKeys(getApplicationContext());
if(cursor.moveToFirst()) {
List<KeyModel> myKeyModelList = new ArrayList<KeyModel>();
int position = 0;
do {
KeyModel key = new KeyModel();
key.setReaderId(cursor.getLong(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry._ID)));
key.setSpName(cursor.getString(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry.SP_NAME)));
key.setReaderDesc(cursor.getString(cursor.getColumnIndexOrThrow(KeyReaderContract.KeyEntry.READER_DESCRIPTION)));
myKeyModelList.add(key);
System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
position++;
} while (cursor.moveToNext());
for(int i = 0; i < myKeyModelList.size(); i++){
KeyModel test = myKeyModelList.get(i);
System.out.println(test.spName+ " "+ test.readerDesc);
}
//create adapter with the arraylist of keys
MyListAdapter mKeyAdapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.key_list_entry, (ViewGroup)findViewById(R.id.main_linear_layout)));
mKeyAdapter.setModel(myKeyModelList);
//set the adapter to the ListView
mKeyListView.setAdapter(mKeyAdapter);
} else{
System.out.println("No keys");
}
}
private class KeyModel{
long readerId;
String spName;
String readerDesc;
public long getReaderId() {
return readerId;
}
public void setReaderId(long readerId) {
this.readerId = readerId;
}
public String getSpName() {
return spName;
}
public void setSpName(String spName) {
this.spName = spName;
}
public String getReaderDesc() {
return readerDesc;
}
public void setReaderDesc(String readerDesc) {
this.readerDesc = readerDesc;
}
View.OnClickListener listener = new View.OnClickListener(){
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, spName, Toast.LENGTH_SHORT).show();
//do other things to delete this once all items are displaying correctly
}
};
}
private class MyListAdapter extends BaseAdapter{
View renderer;
List<KeyModel> keys;
// call this one and pass it layoutInflater.inflate(R.layout.key_list_entry)
public MyListAdapter(View renderer) {
this.renderer = renderer;
}
// whenever you need to set the list of keys just use this method.
// call it when you have the data ready and want to display it
public void setModel(List<KeyModel> keys){
this.keys = keys;
System.out.println(keys.size());
notifyDataSetChanged();
}
@Override
public int getCount() {
if(keys!=null){
return keys.size();
}
return 0;
}
@Override
public Object getItem(int position) {
if(keys!=null){
return keys.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
if(keys!=null){
System.out.println("item id "+ position);
return position;
}
System.out.println(-1);
return -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView==null){
convertView = renderer;
}
KeyModel key = keys.get(position);
System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
TextView rIdView = (TextView)convertView.findViewById(R.id.key_id);
rIdView.setText(Long.toString(key.readerId));
TextView spNameView = (TextView)convertView.findViewById(R.id.sp_name);
spNameView.setText(key.spName);
TextView readerDescView = (TextView)convertView.findViewById(R.id.reader_desc);
readerDescView.setText(key.readerDesc);
Button button = (Button)convertView.findViewById(R.id.delete_keyButton);
button.setOnClickListener(key.listener);
convertView.setVisibility(View.VISIBLE);
return convertView;
}
}
activity_main.xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The first child in the layout is for the main Activity UI-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/main_list_layout">
<TextView
android:id="@+id/display_username"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/keyList"
android:orientation="vertical" >
</ListView>
</LinearLayout>
<!-- Side navigation drawer UI -->
<ListView
android:id="@+id/navList"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#424242"/>
key_list_entry.xml:
<?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:id="@+id/main_linear_layout">
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.05">
<TextView
android:id="@+id/key_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.35">
<TextView
android:id="@+id/sp_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.35">
<TextView
android:id="@+id/reader_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dip"
android:layout_height="fill_parent"
android:layout_weight="0.25">
<Button
android:id="@+id/delete_keyButton" style="?android:textAppearanceSmall"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/delete" android:textStyle="bold" />
</RelativeLayout>
在MyListAdapter的GetView方法中的print语句中:System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
它在调用该方法时正确打印列表中的 4 个元素中的每一个:
这是输出:
09-28 20:23:47.731 20156-20156/com.blah.blah I/System.out﹕ 0 Company1 Front door
09-28 20:23:47.745 20156-20156/com.blah.blah I/System.out﹕ 1 Company1 Back Door
09-28 20:23:47.745 20156-20156/com.blah.blah I/System.out﹕ 2 Occipitech Front door
09-28 20:23:47.746 20156-20156/com.blah.blah I/System.out﹕ 3 Occipitech Garage door
再次感谢您的帮助!这是我的第一个 post,所以如果我做错了什么或者您需要更多信息,请告诉我。我认为问题可能出在我对 BaseAdapter 的实现中,因为列表本身包含所有正确的信息。
不能在所有列表项中使用单一视图。列表中显示的所有行必须是根据传递的数据循环的唯一视图。
所以改变..
if(convertView==null){
convertView = renderer;
}
至
if(convertView==null){
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.key_list_entry);
}