I am having some trouble learning the ins and outs of the SQLite world. I have some code that is allowing me to enter data into a DB. But what i want to do is return this data into a listview. At the moment all I could figure out to do was to have each row printed in a toast after a new entry is added. Can someone please show me how to alter my code to print it in a listview? Or to even look at my code and see that i am going about it in the right way. Thanks
This is the code i am using which calls a display record function
//---get all Records---
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(this);
db.open();
Cursor c = db.getAllRecords();
if (c.moveToFirst())
{
do {
DisplayRecord(c);
} while (c.moveToNext());
}
db.close();
This is the display record function
public void DisplayRecord(Cursor c)
{
Toast.makeText(this,
"id: " + c.getString(0) + "\n" +
"Item: " + c.getString(1) + "\n" +
"Litres: " + c.getString(2),
Toast.LENGTH_SHORT).show();
}
I know i need to change the second function but i dont know how to do that to make it print into a listview
this is the code of getting data from database and insert into Arraylist and insert into arrayAdapter and than display it in listview .
i just done some editing in your existing code.
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(this);
db.open();
ArrayList<String> data_list=new ArrayList<String>();
ListView lv=(ListView)findViewById(R.id.listView1);
Cursor c = db.getAllRecords();
if (c.moveToFirst())
{
do {
data_list.add(c.getString(0));
DisplayRecord(c);
} while (c.moveToNext());
}
ArrayAdapter<String> aa=new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, data_list);
lv.setAdapter(aa);
lv - is the object of ListView.
Create a ListView. Then provide cursorAdapter to the ListView as it's adapter to bind the data in the database to the ListView.
There are examples in the samples folder of the SDK you downloaded in the project called ApiDemos.
You need to have, 1) listview, 2) Object class, 3) Custom Adapter
Here I have just tried to implement as per your requirement.
Since I dont have db I did not try to run. The point to is to five you idea.
Because listview is widget that we use more frequently in android. This is the best approach as per my knowledge.
Layouts that required,
activity_list.xml :
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".ListActivity" >
<ListView
android:id="#+id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
</RelativeLayout>
row_item.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="#+id/Item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Item" />
<TextView
android:id="#+id/Litres"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="litres" />
</LinearLayout>
ListActivity.java :
public class ListActivity extends Activity {
ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
ListView list;
ListAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
list = (ListView) findViewById(R.id.list);
listAdapter = new ListAdapter(ListActivity.this, rowDataArrayList);
list.setAdapter(listAdapter);
getDataFromDB();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list, menu);
return true;
}
private void getDataFromDB() {
rowDataArrayList.clear();
com.example.rory.dbtest.DBAdapter db = new com.example.rory.dbtest.DBAdapter(
this);
db.open();
Cursor c = db.getAllRecords();
if (c.moveToFirst()) {
do {
/**
* Set your data in class
*/
RowData rowData = new RowData();
rowData.setId(c.getString(0));
rowData.setItem(c.getString(1));
rowData.setLitres(c.getString(2));
rowDataArrayList.add(rowData);
} while (c.moveToNext());
}
db.close();
/**
* To reflect new data set change in listview
*/
listAdapter.notifyDataSetChanged();
}
}
RowData.java : Model[pojo] class to save data and to bind in custom adapter.
public class RowData {
String Id;
String Item;
String Litres;
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getItem() {
return Item;
}
public void setItem(String item) {
Item = item;
}
public String getLitres() {
return Litres;
}
public void setLitres(String litres) {
this.Litres = litres;
}
}
ListAdapter.java : custom adapter to bind in listview
public class ListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
public ListAdapter(Context context, ArrayList<RowData> rowData) {
mContext = context;
rowDataArrayList = rowData;
}
#Override
public int getCount() {
return rowDataArrayList == null ? 0 : rowDataArrayList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
Holder holder = new Holder();
view = View.inflate(mContext, R.layout.row_item, null);
holder.tvtItem = (TextView) view.findViewById(R.id.Item);
holder.tvtLitres = (TextView) view.findViewById(R.id.Litres);
view.setTag(holder);
} else {
view = convertView;
}
Holder holder = (Holder) view.getTag();
holder.tvtItem.setText(rowDataArrayList.get(position).getItem());
holder.tvtLitres.setText(rowDataArrayList.get(position).getLitres());
return view;
}
class Holder {
TextView tvtItem;
TextView tvtLitres;
}
}
public class ListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<RowData> rowDataArrayList = new ArrayList<RowData>();
public ListAdapter(Context context, ArrayList<RowData> rowData) {
mContext = context;
rowDataArrayList = rowData;
}
#Override
public int getCount() {
return rowDataArrayList == null ? 0 : rowDataArrayList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
Holder holder = new Holder();
view = View.inflate(mContext, R.layout.row_item, null);
holder.tvtItem = (TextView) view.findViewById(R.id.Item);
holder.tvtLitres = (TextView) view.findViewById(R.id.Litres);
view.setTag(holder);
} else {
view = convertView;
}
Holder holder = (Holder) view.getTag();
holder.tvtItem.setText(rowDataArrayList.get(position).getItem());
holder.tvtLitres.setText(rowDataArrayList.get(position).getLitres());
return view;
}
class Holder {
TextView tvtItem;
TextView tvtLitres;
}
}
Related
I'm trying to implement a selection activity for a given list of items. Each item is checkable, so I have an item with a TextView and a CheckBox. I implemented a ListView for displaying all the options and a Spinner for showing only the "Top Ten" choices, as a subset of the same list. For now I'm showing all the items in both ListView and Spinner.
I want for the items in the ListView to update when the user selects an item in the Spinner (Note: The reverse path works fine, as the Spinner grabs the updated ArrayList each time it dropsdown).
I tried to implement setOnItemSelectedListener for my Spinner, and to call notifyOnDataSetChanged() for my ListViewAdapter inside the Listener. But the Listener is only called on collapse and I get a weird (maybe unrelated) warning message.
The onItemSelectedListener for the Spinner only runs when the Spinner gets collapsed. But notifyOnDataSetChanged() seems to ignore the checked status of the items as a change. How can I make the first option run everytime I check an item and have the change get properly received by the ListAdapter?
Here's the Activity.java code:
public class TriageReasonActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_triage_reason);
final String[] select_qualification = {
"Select Qualification", "10th / Below", "12th", "Diploma", "UG",
"PG", "Phd"};
Spinner spinner = (Spinner) findViewById(R.id.top_reasons_spinner);
ListView symptoms_list = (ListView) findViewById(R.id.view_list_symptoms);
ArrayList<Symptoms> listVOs = new ArrayList<>();
for (int i = 0; i < select_qualification.length; i++) {
Symptoms reason = new Symptoms();
reason.setTitle(select_qualification[i]);
reason.setSelected(false);
listVOs.add(reason);
}
SymptomsListAdapter mListAdapter = new SymptomsListAdapter(this, 0,
listVOs);
SymptomsSpinnerAdapter mSpinnerAdapter = new SymptomsSpinnerAdapter(this, 0,
listVOs);
symptoms_list.setAdapter(mListAdapter);
spinner.setAdapter(mSpinnerAdapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
Log.i("Item selected", "but not cahnged");
symptoms_list.invalidateViews();
mListAdapter.notifyDataSetInvalidated();
}
#Override
public void onNothingSelected(AdapterView<?> parentView) {
Log.i("Not item selected", "but actually it did");
}
});
}
The SpinnerCustom Adapter code:
public class SymptomsSpinnerAdapter extends ArrayAdapter<Symptoms>{
private Context mContext;
private ArrayList<Symptoms> listState;
private SymptomsSpinnerAdapter myAdapter;
private boolean isFromView = false;
/*#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
//mNotifyOnChange = true;
}*/
public SymptomsSpinnerAdapter(Context context, int resource, List<Symptoms> objects) {
super(context, resource, objects);
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
this.myAdapter = this;
}
#Override
public View getDropDownView(int position, View convertView,
ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
private TextView mTextView;
private CheckBox mCheckBox;
}
}
Here's the (almost identical) ListAdapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
private Context mContext;
private ArrayList<Symptoms> listState;
private boolean isFromView = false;
public SymptomsListAdapter(Context context, int resource, List<Symptoms> objects) {
this.mContext = context;
this.listState = (ArrayList<Symptoms>) objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView,
ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
LayoutInflater layoutInflator = LayoutInflater.from(mContext);
convertView = layoutInflator.inflate(R.layout.item_reasons, null);
holder = new SymptomsListAdapter.ViewHolder();
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
holder.mCheckBox = (CheckBox) convertView.findViewById(R.id.checkbox);
convertView.setTag(holder);
} else {
holder = (SymptomsListAdapter.ViewHolder) convertView.getTag();
}
holder.mTextView.setText(listState.get(position).getTitle());
// To check weather checked event fire from getview() or user input
isFromView = true;
holder.mCheckBox.setChecked(listState.get(position).isSelected());
isFromView = false;
if ((position == 0)) {
holder.mCheckBox.setVisibility(View.INVISIBLE);
} else {
holder.mCheckBox.setVisibility(View.VISIBLE);
}
holder.mCheckBox.setTag(position);
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
if (!isFromView) {
listState.get(position).setSelected(isChecked);
}
}
});
return convertView;
}
#Override
public int getCount() {
return listState.size();
}
#Override
public Symptoms getItem(int position) {
if( position < 1 ) {
return null;
}
else {
return listState.get(position-1);
}
}
#Override
public long getItemId(int position) {
return 0;
}
private class ViewHolder {
public TextView mTextView;
public CheckBox mCheckBox;
}
}
And here's the warning I'm getting:
W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
EDIT: Adding the layouts and the model class in case they may cause an issue:
Activity Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demo.hb.activity.visit.TriageReasonActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textFontWeight="6dp"
android:textSize="30sp"
android:layout_margin="20dp"
android:textAlignment="center"
android:textColor="#000000"
android:text="What is the reason for your visit?" />
<Spinner
android:id="#+id/top_reasons_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/btn_dropdown"
android:spinnerMode="dropdown"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="end">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/view_list_symptoms"
android:layout_above="#+id/next_btn"
android:layout_alignParentTop="true"/>
</RelativeLayout>
</LinearLayout>
</FrameLayout>
Item layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="text"
android:textAlignment="gravity" />
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" />
</RelativeLayout>
Model Class:
public class Symptoms {
private String title;
private boolean selected;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
}
The reason that nothing is changing is because you haven't implemented the method to handle the data set changes. You need to handle how the data is reloaded in your adapter:
public class SymptomsListAdapter extends BaseAdapter implements ListAdapter {
...
public void refreshData(ArrayList<Symptoms> objects){
this.listState = (ArrayList<Symptoms>) objects;
notifyDataSetChanged();
}
...
}
This link does a great job of explaining how the notifyDataSetInvalidated() works (or in your case, why it's not working).
I have a list of a POJO in an Android app and I am currently displaying one of the fields in a listview/listitem like so:
List<NotificationItem> notifItems;
// snip, populate
ArrayAdapter adapter = new ArrayAdapter<>(this, R.layout.notification_item, notifItems);
ListView listView = (ListView) findViewById(R.id.notification_listview);
listView.setAdapter(adapter);
And it is my understanding that the listivew or adapter uses the toString of the POJO, which is
public String toString() {
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd hh:mm");
return _notificationTitle + " | " + dateFormatter.format(_notificationReceivedDate);
}
R.id.notificationitem is
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/label"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip"
android:textSize="16sp"
android:textStyle="bold"></TextView>
So far so good, but what I want to do is add elements to the notificationitem layout file and then update the Java code to populate the new fields.
How is this done? I don't really understand how the adapter knows/puts the toString value into the one field in the notificationitem.
public class NotificationItem {
//your fields here
}
//-----------------------
public class NotifAdapter extends BaseAdapter {
Context context;
List<NotificationItem> data;
public NotifAdapter(Context context, List<NotificationItem> data) {
this.context = context;
this.data = data;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.your_row_layout,parent, null);
TextView tx = convertView.findViewById(R.id.your_widget_inside_row_layout);
tx.setText(data.yourDataPropery);
return convertView;
}
}
// In your activity
NotifAdapter adapter = new NotifAdapter(this, ArrayList<NotificationItem>);
listView.setAdapter(adapter);
I am trying to fill my list from database using BaseAdapter. Logcat don't show any error. Here is my code.
In this DatabaseHelper class, I have one table STUDENTS.
DatabaseHelper.java
public long saveData(Student std) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("NAME",std.name);
cv.put("CITY",std.city);
cv.put("AGE",std.age);
long id = db.insert("STUDENTS", null, cv);
db.close();
return id;
}
public ArrayList<Student> getAllStudent() {
ArrayList<Student> studentArrayList = new ArrayList<Student>();
SQLiteDatabase db = getWritableDatabase();
Cursor cursor = db.query("STUDENTS",null,null,null,null,null,null);
Log.e("COUNT",""+cursor.getCount());
while (cursor.moveToNext()) {
Student s = new Student();
s.name = cursor.getString(cursor.getColumnIndex("NAME"));
s.city = cursor.getString(cursor.getColumnIndex("CITY"));
s.age = cursor.getString(cursor.getColumnIndex("AGE"));
studentArrayList.add(s);
}
db.close();
return studentArrayList;
}
MyBaseAdapter.java
public class MyBaseAdapter extends BaseAdapter {
ArrayList<Student> myList = new ArrayList<Student>();
LayoutInflater inflater;
Context context;
public MyBaseAdapter(Context context,ArrayList<Student> myList) {
this.myList = myList;
this.context = context;
inflater = LayoutInflater.from(this.context);
}
#Override
public int getCount() {
return myList.size();
}
#Override
public Student getItem(int position) {
return myList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
myViewHolder viewHolder;
if(convertView == null){
convertView = inflater.inflate(R.layout.single_row, null);
viewHolder = new myViewHolder();
convertView.setTag(viewHolder);
} else {
viewHolder = (myViewHolder) convertView.getTag();
}
viewHolder.nameTextView = (TextView) convertView.findViewById(R.id.nameTextView);
viewHolder.cityTextView = (TextView) convertView.findViewById(R.id.cityTextView);
viewHolder.ageTextView = (TextView) convertView.findViewById(R.id.ageTextView);
viewHolder.nameTextView.setText(myList.get(position).name);
viewHolder.cityTextView.setText(myList.get(position).city);
viewHolder.ageTextView.setText(myList.get(position).age);
return convertView;
}
public class myViewHolder {
TextView nameTextView, cityTextView, ageTextView;
}
}
This is my model class
Student.java
public class Student {
String name;
String city;
String age;
}
and in my MainActivity I am trying to fill data into list.
MainActivity.java
public class MainActivity extends ActionBarActivity {
public EditText searchEditText;
public Button addButton;
public ListView studentListView;
public DatabaseHelper dbHelper;
public ArrayList<Student> arrayList;
public MyBaseAdapter myBaseAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
searchEditText = (EditText)findViewById(R.id.searchEditText);
addButton = (Button)findViewById(R.id.addButton);
studentListView = (ListView) findViewById(R.id.studentListView);
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this,AddNewStudent.class);
startActivity(i);
}
});
dbHelper = new DatabaseHelper(getApplicationContext());
arrayList = dbHelper.getAllStudent();
myBaseAdapter = new MyBaseAdapter(MainActivity.this,arrayList);
studentListView.setAdapter(myBaseAdapter);
myBaseAdapter.notifyDataSetChanged();
}
}
single_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
android:id="#+id/container">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/nameTextView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/cityTextView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/ageTextView" />
</LinearLayout>
I don't know where I went wrong.
Finally, I have found the answer for this. You just need to add couple of line in getView() method to assign value from list to model class object.
public View getView(int position, View convertView, ViewGroup parent) {
Student std = new Student(); //this line I added
std = myList.get(position); //this line I added
myViewHolder viewHolder;
if(convertView == null){
convertView = inflater.inflate(R.layout.single_row, null);
viewHolder = new myViewHolder();
convertView.setTag(viewHolder);
} else {
viewHolder = (myViewHolder) convertView.getTag();
}
viewHolder.nameTextView = (TextView) convertView.findViewById(R.id.nameTextView);
viewHolder.cityTextView = (TextView) convertView.findViewById(R.id.cityTextView);
viewHolder.ageTextView = (TextView) convertView.findViewById(R.id.ageTextView);
viewHolder.nameTextView.setText(myList.get(position).name);
viewHolder.cityTextView.setText(myList.get(position).city);
viewHolder.ageTextView.setText(myList.get(position).age);
return convertView;
}
Java:
dateInserted = getDateFromDatePicker(datePicker);
calendarDateInserted.setTime(dateInserted);
finalDateShown = getStringRepresentationOfDate(calendarDateInserted.get(Calendar.DAY_OF_WEEK)) + " " + (calendarDateInserted.get(Calendar.MONTH) + 1) + "/" + (calendarDateInserted.get(Calendar.DATE)) + "/" + (calendarDateInserted.get(Calendar.YEAR));
Log.d("debug",finalDateShown); // Print the string to the LogCat
;
myArrayAdapter.add(new MyItem(finalDateShown));
MyArrayAdapter class:
private class MyArrayAdapter extends ArrayAdapter<MyItem> // My custom array adapter class
{
private int myResourceId = 0;
private LayoutInflater myLayoutInflater;
private RadioButton mySelectedRadioButton;
private int mSelectedPosition = -1;
private ButtonClickListener myClickListener = null;
public MyArrayAdapter(Context context, int myResourceId, List<MyItem> objects,ButtonClickListener myClickListener)
{
super(context, myResourceId, myItemList);
this.myResourceId = myResourceId;
myLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.myClickListener = myClickListener;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
View view = convertView;
final ViewHolder holder;
if (view == null)
{
view = myLayoutInflater.inflate(myResourceId, parent, false);
holder = new ViewHolder();
holder.dateTextView = (TextView) view.findViewById(R.id.dates_id);
holder.addDateButton = (Button) view.findViewById(R.id.add_date_button_id);
holder.addCommentButton = (Button)view.findViewById(R.id.add_comment_button_id);
holder.selectDateRadioButton = (RadioButton) view.findViewById(R.id.select_date_radio_button_id);
holder.addDateButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(position != mSelectedPosition && mySelectedRadioButton != null)
{
mySelectedRadioButton.setChecked(false);
}
mSelectedPosition = position;
mySelectedRadioButton = holder.selectDateRadioButton;
Log.d("debug", finalDateShown);
add(new MyItem(finalDateShown));
}
});
view.setTag(holder);
}
else
{
holder = (ViewHolder) view.getTag();
}
if(mSelectedPosition != position)
{
holder.selectDateRadioButton.setChecked(false);
}
else
{
holder.selectDateRadioButton.setChecked(true);
if(mySelectedRadioButton != null && holder.selectDateRadioButton != mySelectedRadioButton)
{
mySelectedRadioButton = holder.selectDateRadioButton;
}
}
return view;
} // End of getView() method
#Override
public void add(MyItem object)
{
super.add(object);
this.setNotifyOnChange(true);
}
private class ViewHolder
{
TextView dateTextView;
Button addDateButton;
Button addCommentButton;
RadioButton selectDateRadioButton;
}
}
Now the TextView is never changed to finalDateShown as it should be.
MyItem class:
class MyItem
{
public String date;
public boolean isRadioButtonChecked;
public MyItem(String date)
{
this.date = date;
this.isRadioButtonChecked = false;
}
}
listViewSingleRow:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/dates_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/date_text"
/>
<Button
android:id="#+id/add_comment_button_id"
android:layout_width="105sp"
android:layout_height="wrap_content"
android:text="#string/add_comment_button_text"
android:layout_toRightOf="#+id/add_date_button_id"
android:layout_toEndOf="#id/add_date_button_id"
/>
<Button
android:id="#+id/add_date_button_id"
android:layout_width="80sp"
android:layout_height="wrap_content"
android:text="#string/add_date_button_text"
android:layout_toRightOf="#id/dates_id"
android:layout_toEndOf="#id/dates_id"
/>
<RadioButton
android:id="#+id/select_date_radio_button_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/add_comment_button_id"
android:layout_toEndOf="#id/add_comment_button_id"
/>
</RelativeLayout>
Every time i use myArraAdapter.add(finalDateShown) its adding it with the android:Text="SomeText" i assigned in the XML instead of finalDateShown.
So whats wrong here?
EDIT:
Activity:
public class SexAcivity extends AppCompatActivity
{
ListView listView;
MyArrayAdapter myArrayAdapter;
List<MyItem> myItemList = new ArrayList<SexAcivity.MyItem>();
public interface ButtonClickListener
{
public abstract void onButtonClick(int position);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sex_acivity);
listView = (ListView) findViewById(R.id.list_view_id);
listView.setLayoutParams(layoutParams);
headerView = ((LayoutInflater)SexAcivity.this.getSystemService(SexAcivity.this.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.list_view_header, null, false);
listView.addHeaderView(headerView);
myArrayAdapter = new MyArrayAdapter(SexAcivity.this,R.layout.list_view_single_row,myItemList,new ButtonClickListener()
{
#Override
public void onButtonClick(int position)
{
}
});
listView.setAdapter(myArrayAdapter);
finalDateShown = getStringRepresentationOfDate(calendarDateInserted.get(Calendar.DAY_OF_WEEK)) + " " + (calendarDateInserted.get(Calendar.MONTH) + 1) + "/" + (calendarDateInserted.get(Calendar.DATE)) + "/" + (calendarDateInserted.get(Calendar.YEAR));
Log.d("debug",finalDateShown); // Print the string to the LogCat
myArrayAdapter.add(new MyItem(finalDateShown));
myArrayAdapter.setNotifyOnChange(true);
}
}
Thats basically it.
Option A: No need to call notifyDataSet or override of the add-method. Just set myAdapter.setNotifyOnChange(true) and it will do all the magic for add, insert, clear and remove. See here. The default value is true. So I wonder why your UI does not update automatically. The list of the adapter should be set in it's constructor and passed to the super-constructor. I see that you do this. And then the adapter should be set to the ListView by calling list.setAdapter.
Option B: First add the item, then call notifyDataSetChanged.
Just a side note: In terms of object oriented programming, you should move the call to notifyDataSetChanged into your implementation of the ArrayAdapter.
private class MyArrayAdapter extends ArrayAdapter<MyItem>
{
#Override
public void add(MyItem object)
{
// add
super.add(object);
// then notify UI
this.notifyDataSetChanged();
}
}
This is a simple listview example
public class Test extends ListActivity {
ArrayList<String> txt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
txt=new ArrayList<String>();
txt.add("diaplay text 1");
txt.add("diaplay text 2");
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, txt));
}
}
But this can only store string
I want do something like this
<ul>
<li data-meta="hidden text 1">display text 1</li>
<li data-meta="hidden text 2">display text 2</li>
</ul>
Because I want store more information in each list item
So I want store this class into listview
public class Item
{
public String displayText;
public String meta;
}
How can I do this?
You have to implement a custom Adapter for that. First we have to fix your view model, you call it Item:
public class Item
{
public String displayText;
public String meta;
}
Those fields should be private with appropriate getters and setters and constructors. If you want to modify such Items in a List you also need to implement equals() and hashCode(). If you do all that your Item class should look something like this:
public class Item {
private String displayText;
private String meta;
public Item(String displayText, String meta) {
this.displayText = displayText;
this.meta = meta;
}
public Item() {
}
public String getDisplayText() {
return displayText;
}
public void setDisplayText(String displayText) {
this.displayText = displayText;
}
public String getMeta() {
return meta;
}
public void setMeta(String meta) {
this.meta = meta;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
if (displayText != null ? !displayText.equals(item.displayText) : item.displayText != null) return false;
return !(meta != null ? !meta.equals(item.meta) : item.meta != null);
}
#Override
public int hashCode() {
int result = displayText != null ? displayText.hashCode() : 0;
result = 31 * result + (meta != null ? meta.hashCode() : 0);
return result;
}
}
Now we need to create a layout for the Items in the ListView, for example something simple like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rlRoot"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:clickable="true"
android:background="#drawable/list_item_background">
<TextView
style="#style/DefaultTextView"
android:id="#+id/tvDisplayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true" />
<TextView
style="#style/DefaultTextView"
android:id="#+id/tvMeta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/tvDisplayText"
android:layout_toStartOf="#id/tvDisplayText"
android:layout_centerVertical="true" />
</RelativeLayout>
In this layout we have two TextViews to display both the Strings from each Item. To increase ListView performance you should always implement the view holder pattern. For this purpose we create a ViewHolder class. Its purpose is to hold a reference to the relevant Views in each row of the ListView so we don't have to perform the expensive findViewById() as often:
public class ViewHolder {
public TextView tvDisplayText;
public TextView tvMeta;
}
Note that we don't need getters and setters or anything in this view holder. We will access the public fields directly.
Now we can implement our custom Adapter. This is actually pretty straight forward, I will comment the most important parts.
public class ExampleAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final List<Item> items;
private ExampleAdapter(Context context, List<Item> items) {
this.inflater = LayoutInflater.from(context);
this.items = items;
}
#Override
public int getCount() {
return this.items.size();
}
#Override
public Item getItem(int position) {
return this.items.get(position);
}
#Override
public long getItemId(int position) {
return this.items.get(position).hashCode();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item item = getItem(position);
if(convertView == null) {
// If convertView is null we have to inflate a new layout
convertView = this.inflater.inflate(R.layout.example_list_item, parent, false);
final ViewHolder viewHolder = new ViewHolder();
viewHolder.tvDisplayText = (TextView) convertView.findViewById(R.id.tvDisplayText);
viewHolder.tvMeta = (TextView) convertView.findViewById(R.id.tvMeta);
// We set the view holder as tag of the convertView so we can access the view holder later on.
convertView.setTag(viewHolder);
}
// Retrieve the view holder from the convertView
final ViewHolder viewHolder = (ViewHolder) convertView.getTag();
// Bind the values to the views
viewHolder.tvDisplayText.setText(item.getDisplayText());
viewHolder.tvMeta.setText(item.getMeta());
return convertView;
}
}
And you would use this custom Adapter like this:
final List<Item> items = new ArrayList<Item>();
items.add(new Item("a", "b"));
items.add(new Item("c", "d"));
items.add(new Item("e", "f"));
items.add(new Item("g", "h"));
final ExampleAdapter adapter = new ExampleAdapter(context, items);
listView.setAdapter(adapter);
You have implementation BaseAdapter, ArrayApdater or somethings.
In your adapter you pass a list of custom objects.
Here a sample code:
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Item> items;
public CustomListAdapter(Activity activity, List<Item> items) {
this.activity = activity;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int location) {
return items.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.yourlayout, null);
Item item = items.get(position);
//Setter text
return convertView;
}
}
Tutorial:
BaseAdapter
Official Documentation
To store custom data in a ListView adapter, you must implement your own. Take a look at Custom BaseAdapter with ListView.
I don't know clearly understand your question. But i understand that. Hope for help.
strings.xml
<string-array name="li_items">
<item >Home</item>
<item >Find People</item>
<item >Photos</item>
<item >Communities</item>
<item >Pages</item>
</string-array>
In your ListActivity
public class Test extends ListActivity {
ArrayList<String> txt;
private String[] liItem;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
liItem= getResources().getStringArray(R.array.li_items);
txt=new ArrayList<String>();
txt.add(liItem[0]);
txt.add(liItem[1]);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, txt));
}
}