Some background information first:
In my android application I have some information in a SQLite database relating to a physical key. This information includes the name of the 'service provider' who issued the key as well as a description of what door the key is for and the id of that door. What I am attempting to do is display all of the information for each 'key' in a row of a ListView
element and have a delete button at the end of the row which can be used to delete that information from the database.
Now the problem is when I have tried this the only entry that displays in the activity is the last one and where the other entries would have been is empty space. See screen shot here: (https://i.sstatic.net/8C15B.png)
The space I outlined in red is the blank space left from where the first 3 entries would be. I have looked this up and all of the responses to this kind of question have been a problem with the way that they have entered the data into the arraylist but I have tested and the arraylist is populated with all 4 entries correctly. I just don't know why they are not displaying and I am relatively new to android so any help would be appreciated!
Here is the code from the relevant files: MainActivity.java: (Complete with my debugging print statements. These print statements all show that there are 4 different entries in the ArrayList after adding them in the do while loop of the addKeyItems() method.)
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>
In the print statement in the GetView method of MyListAdapter: System.out.println(position+ " "+ key.getSpName()+ " "+ key.getReaderDesc());
It prints each of the 4 elements in the list correctly as that method is called:
Here is the ouput:
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
Again any help would be appreciated! This is my first post so let me know if I have done something wrong or you need any more information. I think the problem may be in my implementation of BaseAdapter, since the list itself has all of the correct information in it.
There must not be single view used in all list item. All rows displayed in list must be a unique view which are recycled according to data passed.
So change ..
if(convertView==null){
convertView = renderer;
}
to
if(convertView==null){
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.key_list_entry);
}