How do you add multiple adapters to a listview? After reading this question and following the tutorial, I still don't have what I want.
Scenario
Adding two types of text into an SQLite database table and retrieving them on another activity in the form of a card with a title on top, a separator, and the content underneath.
Visuals
Adding content to main list:
Card on main list:
My Code
I take it no one really needs to see the layout for the edittext part so I'll jump right to the main card row item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="#drawable/card_selecter_background">
<TextView
android:id="#+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample"
android:textSize="30sp"/>
<View
android:id="#+id/separator"
android:layout_marginTop="5dp"
android:layout_marginBottom="2dp"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#android:color/darker_gray"/>
<TextView
android:id="#+id/tvContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample"
android:textSize="22sp"/>
</LinearLayout>
This is where I add the edittext strings to the database:
db.execSQL("CREATE TABLE IF NOT EXISTS Lists (Title VARCHAR, Content VARCHAR);");
addListBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean cancel = false;
String listName = listNameET.getText().toString();
String content = contentET.getText().toString();
if (TextUtils.isEmpty(listName)) {
listNameET.setError("Please enter a list name.");
cancel = true;
} else if (listName.contains("'") || listName.contains("\"")) {
listNameET.setError("Please enter alphanumeric (abc123) characters only.");
cancel = true;
}
if (TextUtils.isEmpty(content)) {
contentET.setError("Field cannot be left blank.");
cancel = true;
} else if (content.contains("'") || content.contains("\"")) {
contentET.setError("Please enter alphanumeric (abc123) characters only.");
cancel = true;
}
if (cancel) {
//Nothing happens
} else {
db.execSQL("INSERT INTO Lists VALUES('" + listName + "', '" + content + "');");
db.close();
finish();
}
}
});
Here is where it is retrieved in the listview activity:
Cursor c = db.rawQuery("SELECT Title from Lists", null);
Cursor c2 = db.rawQuery("SELECT Content from Lists", null);
final ArrayList<String> titleList = new ArrayList<String>();
final ArrayList<String> contentList = new ArrayList<String>();
if (c.moveToFirst() && c2.moveToFirst()) {
do {
titleList.add(c.getString(c.getColumnIndex("Title")));
contentList.add(c2.getString(c2.getColumnIndex("Content")));
} while (c.moveToNext() && c2.moveToNext());
}
ArrayAdapter<String> titleAdapter = new ArrayAdapter<String>(MainActivity.this, R.layout.listname_row, R.id.tvTitle, titleList);
ArrayAdapter<String> contentAdapter = new ArrayAdapter<String>(MainActivity.this, R.layout.listname_row, R.id.tvContent, contentList);
ListView lv = (ListView) findViewById(R.id.listOfNames);
//Since Java works top to bottom, the contentAdapter is set even though
//this line is here.
lv.setAdapter(titleAdapter);
lv.setAdapter(contentAdapter);
db.close();
c.close();
I need to be able to attach the title and the content to the same listview.
Help is much appreciated!
You can create a custom Adapter like this:
class ExampleAdapter extends BaseAdapter{
List<String> mTitles;
List<String> mContents;
#Override
public int getCount() {
return mTitles.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 v;
//inflate view if needed
...
TextView tv_title;
TextView tv_content;
String title = mTitles.get(position);
String content = mContents.get(position);
tv_title.setText(title);
tv_content.setText(content);
return v;
}
}
Now past 2 list of String to this Adapter and call setAdapter of ListView.
Related
I have a list view that gets populated from a database. On the same activity I also have an EditTExt and an Add Category Button above the listview.
EditText | Add Category
Category Name1 | Edit Button | Delete Button
Category Name2 | Edit Button | Delete Button
Category Name3 | Edit Button | Delete Button
If I Add Category, the listview updates.
If I click on Delete, Opens Up Dialog (Are You Sure?), when you click yes it deletes it from the database and then updates the listview with the row deleted.
If I click the edit button (which is in the custom adapter for the listview layout), it opens up the dialog and shows an edittext with the category name and you can change it and when you click on the save button it saves it to the database but DOES NOT update the listview.
So I solved the issue instead of trying to repoll the database to update the listview again, I grabbed the position and the edittext for the category of that row and updated it that way.
Being only 1 item can be edited at a time I figured no big deal until I ran into another issue by using this work around. And that is:
If you click on Edit Button For Category Name1 and in the dialog you rename it to Meaningful Category Name. It updates the database, it is reflected in the listview right away, but when you delete the item before doing anything else when I send the message to a different listview to let me know that it was deleted, it reflects the original category name and not the edited one.
Now the work around for this is that when I want to delete it, instead of relying on the category name from the listview, get the category name from the database before it's deleted, then delete it and then send the message with the category name from the database.
What I would really like instead of using the 2 workarounds is the following flow:
Activity Loads With Custom Listview -> Click on Edit -> Dialog Edit Opens From Custom Adapter -> Click on Save Button -> Database is updated. -> Listview is updated / refreshed.
I have it all working with the exception of Listview is updated / refreshed.
I have searched high and low and can find all kinds of things that you can do to refresh listview, but none of them work and none of them are for Database update from within a dialog in the custom adapter.
I can post code, but I thought this is pretty much straight forward. If not I will gladly post code.
Perhaps consider using a CursorAdapter which eliminates the need for an intermediate Array and refreshing is a breeze.
Here's an example, that uses the SimpleCursorAdapter, that does all but edit (however you may well want a Custom Cursor Adapter). However the refresh aspect is no different bar the specific adapter type.
The layout activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
/>
<EditText
android:id="#+id/categoryname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</EditText>
<Button
android:id="#+id/addcategorybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ADD CATEGORY"
>
</Button>
<ListView
android:id="#+id/categorylist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ListView>
</LinearLayout>
i.e. EditText, Add Button and ListView
The Database Helper DBHelper
class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "category.db";
public static final int DBVERSION = 1;
public static final String TB_CATEGORY = "category";
public static final String COl_ID_CATEGORY = BaseColumns._ID;
public static final String COl_CATEGORYNAME_CATEGORY = "category_name";
private SQLiteDatabase db;
private static volatile DBHelper instance;
private DBHelper(#Nullable Context context) {
super(context, DBNAME, null, DBVERSION);
db = this.getWritableDatabase();
}
public static DBHelper getInstance(Context context) {
if (instance == null) {
instance = new DBHelper(context);
}
return instance;
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TB_CATEGORY + "(" +
COl_ID_CATEGORY + " INTEGER PRIMARY KEY" +
"," + COl_CATEGORYNAME_CATEGORY + " TEXT UNIQUE " +
")");
}
#Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long insertCategory(String categoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,categoryName);
return db.insert(TB_CATEGORY,null,cv);
}
public int deleteCategory(long id) {
return db.delete(TB_CATEGORY,COl_ID_CATEGORY + "=?", new String[]{String.valueOf(id)});
}
public int deleteCategory(String categoryName) {
return db.delete(TB_CATEGORY,COl_CATEGORYNAME_CATEGORY + "=?",new String[]{categoryName});
}
public int updateCategory(Long id, String categoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,categoryName);
return db.update(TB_CATEGORY,cv,COl_ID_CATEGORY+"=?", new String[]{String.valueOf(id)});
}
public int updateCategory(String oldCatgeoryName, String newCategoryName) {
ContentValues cv = new ContentValues();
cv.put(COl_CATEGORYNAME_CATEGORY,newCategoryName);
return db.update(TB_CATEGORY,cv,COl_CATEGORYNAME_CATEGORY + "=?",new String[]{oldCatgeoryName});
}
public Cursor getCategories() {
return db.query(TB_CATEGORY,null,null,null,null,null,COl_CATEGORYNAME_CATEGORY + " ASC");
}
}
NOTE Cursor adapters expect(must have) a column named _id (hence BaseColumns._ID) and that column should be a unique integer that identiofies the row. Most often an alias of the rowid column aka column is defined using _id INTEGER PRIMARY KEY (with or without AUTOINCREMENT (without is more efficient, with is rarely required so best not used)).
As you can see simple two column table _id and categoryname. methods to add, update, insert, delete and extract all rows (as a Cursor) have been added.
The Activity MainActivity :-
public class MainActivity extends AppCompatActivity {
EditText categoryName;
Button addCategory;
ListView categoryList;
SimpleCursorAdapter sca;
DBHelper db;
Cursor csr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
categoryName = this.findViewById(R.id.categoryname);
addCategory = this.findViewById(R.id.addcategorybutton);
categoryList = this.findViewById(R.id.categorylist);
db = DBHelper.getInstance(this);
setupAddCategoryButton();
setOrRefreshCategoryListView();
}
public void setOrRefreshCategoryListView() {
csr = db.getCategories();
if (sca == null) {
sca = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,
csr, //<<<<<<<< The Cursor
new String[]{DBHelper.COl_CATEGORYNAME_CATEGORY}, //<<<<<<<< The list of columns to be displayed
new int[]{android.R.id.text1}, //<<<<<<<< The corresponding view id's in the layout that is to display the data from the column
0
);
categoryList.setAdapter(sca);
categoryList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
DBHelper dbx = DBHelper.getInstance(view.getContext());
if (dbx.deleteCategory(l) > 0) {
setOrRefreshCategoryListView();
}
return true;
}
});
} else {
sca.swapCursor(csr);
}
}
public void setupAddCategoryButton() {
addCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (categoryName.getText().toString().length() > 0) {
if (db.insertCategory(categoryName.getText().toString()) > 0) {
setOrRefreshCategoryListView();
}
categoryName.setText("");
}
}
});
}
}
See the setOrRefreshCategoryListView, all that is needed to refresh (and initially setup the ListView) is done in here. You just have to call the method.
When the above is run. Categories can be added by entering text and then clicking the ADD CATEGORY button. Categories can be deleted by long clicking a Category.
Result
After adding a few categories (1-3) and just before adding a 4th :-
Click on Add :-
Long Click Category 2 :-
Additional re comment
I was just hiping that there was a way to refresh the listview from within the custom adapter itself after the update from the alertdialog.
perhaps consider the following which shows both refresh from within the adapter (i.e. hot DLT button and item is deleted and refreshed)
and also from the invoking activity via the EDIT button (doesn't edit just toasts).
First the layout used for the CustomAdapter
subclass of CursorAdapter which I would still recommend over ArrayAdapter (i.e. CursorAdapter exists for a reason).
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/categoryname"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="6">
</TextView>
<Button
android:id="#+id/categoryedit"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
android:text="EDIT"
android:onClick="onClickEditCategoryButton"
android:layout_marginRight="2dp"
>
</Button>
<Button
android:id="#+id/categorydelete"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent"
android:text="DLT"
>
</Button>
</LinearLayout>
NOTE the EDIT button has onCLick specified so onClicklistener code is coded on your behalf.
DBHelper is unchanged from above.
MainActivity is now :-
public class MainActivity extends AppCompatActivity {
EditText categoryName;
Button addCategory;
ListView categoryList;
CustomAdapter ca;
DBHelper db;
Cursor csr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
categoryName = this.findViewById(R.id.categoryname);
addCategory = this.findViewById(R.id.addcategorybutton);
categoryList = this.findViewById(R.id.categorylist);
db = DBHelper.getInstance(this);
setupAddCategoryButton();
setOrRefreshCustomCategoryListView();
}
public void setOrRefreshCustomCategoryListView() {
csr = db.getCategories();
if (ca == null) {
ca = new CustomAdapter(this,csr);
categoryList.setAdapter(ca);
} else {
ca.swapCursor(csr);
}
}
public void onClickEditCategoryButton(View v) {
switch (v.getId()) {
case R.id.categoryedit: {
Toast.makeText(this, "You Clicked Edit for Category with ID of " + v.getTag(), Toast.LENGTH_SHORT).show();
setOrRefreshCustomCategoryListView();
}
break;
}
}
public void setupAddCategoryButton() {
addCategory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (categoryName.getText().toString().length() > 0) {
if (db.insertCategory(categoryName.getText().toString()) > 0) {
setOrRefreshCustomCategoryListView();
}
categoryName.setText("");
}
}
});
}
}
Last the CustomAdapter :-
class CustomAdapter extends CursorAdapter {
CustomAdapter(Context context, Cursor csr) {
super(context,csr, android.widget.CursorAdapter.IGNORE_ITEM_VIEW_TYPE);
}
#Override
public View newView(Context context, Cursor csr, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.categorylist,parent,false);
}
#Override
public void bindView(View view, Context context, Cursor csr) {
TextView categoryName = view.findViewById(R.id.categoryname);
categoryName.setText(csr.getString(csr.getColumnIndex(DBHelper.COl_CATEGORYNAME_CATEGORY)));
// Set Button tags with id of current row
// NOTE button onClick listener set in layout
String id = csr.getString(csr.getColumnIndex(DBHelper.COl_ID_CATEGORY));
view.findViewById(R.id.categoryedit).setTag(id);
view.findViewById(R.id.categorydelete).setTag(id);
view.findViewById(R.id.categorydelete).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context,"You Clicked Delete",Toast.LENGTH_SHORT).show();
DBHelper.getInstance(context).deleteCategory(Long.parseLong(view.getTag().toString()));
refreshListView(context);
}
});
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return super.getView(position, convertView, parent);
}
public void refreshListView(Context context) {
this.swapCursor(DBHelper.getInstance(context).getCategories());
}
}
result
Looks like this now (clicking Edit toasts (via activity), clicking DLT deletes (via adapter))
For my Android project, I have a listview which has a checkbox for every item. The data is loaded from an SQLite database by using a CursorAdapter class. However, whenever I scroll, the checkbox positions will get moved and get carried down to the next part of the listview. How can I fix this problem?
GIF of my CheckBox Problem
Here's my Cursor Adapter Class:
public class VocabCursorAdapter extends CursorAdapter {
private static final int DIFFICULT = 0;
private static final int FAMILIAR = 1;
private static final int EASY = 2;
private static final int PERFECT = 3;
public VocabCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, 0);
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return LayoutInflater.from(context).inflate(R.layout.item_vocab, parent, false);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
// Find fields to populate in inflated template
TextView tvVocabName = (TextView) view.findViewById(R.id.vocabName);
TextView tvVocabDefinition = (TextView) view.findViewById(R.id.vocabDefinition);
ImageView tvVocabLevel = (ImageView) view.findViewById(R.id.vocabLevel);
// Extract properties from cursor
String vocab = cursor.getString(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_VOCAB));
String definition = cursor.getString(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_DEFINITION));
int level = cursor.getInt(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_LEVEL));
// Populate fields with extracted properties
tvVocabName.setText(vocab);
tvVocabDefinition.setText(definition);
if (level == DIFFICULT) {
tvVocabLevel.setImageResource(R.drawable.level_bars_difficult);
tvVocabLevel.setTag(DIFFICULT);
}
else if (level == FAMILIAR) {
tvVocabLevel.setImageResource(R.drawable.level_bars_familiar);
tvVocabLevel.setTag(FAMILIAR);
}
else if (level == EASY) {
tvVocabLevel.setImageResource(R.drawable.level_bars_easy);
tvVocabLevel.setTag(EASY);
}
else if (level == PERFECT) {
tvVocabLevel.setImageResource(R.drawable.level_bars_perfect);
tvVocabLevel.setTag(PERFECT);
}
}
And here's my list item xml, item_vocab.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:longClickable="true">
<ImageView
android:layout_width="36sp"
android:layout_height="36sp"
android:id="#+id/vocabLevel"
android:layout_gravity="right"
android:src="#drawable/level_bars"
android:scaleType="fitXY"
android:contentDescription="#string/vocab_level"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/editCheckbox"
android:layout_toStartOf="#+id/editCheckbox"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/vocabName"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#+id/vocabLevel"
android:layout_toStartOf="#+id/vocabLevel"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/vocabDefinition"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_toLeftOf="#+id/vocabLevel"
android:layout_toStartOf="#+id/vocabLevel"
android:layout_below="#id/vocabName"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/editCheckbox"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
And here's my xml which contains a listview
<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=".controller.MyVocab"
android:paddingLeft="5dp">
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/mVocabList"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/empty_text_view"
android:id="#android:id/empty"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
</RelativeLayout>
I have looked at a lot of different solutions on StackOverflow, but I wasn't able to successfully do it in my own app. For an example, this post has a similar problem, but its solution used getView and I had trouble understanding how to implement it with newView and bindView instead.
And some other solutions might be examples where a cursoradapter is not involved. Any help is much appreciated, thanks a lot!
Edit #1: After incorporating Phan's changes, the checkbox states get resets to false rather than keeping its states when I scroll the listview (See ).
Reason : ListView re-uses the views.
Solution :
class VocabCursorAdapter extends CursorAdapter {
List<Integer> selectedItemsPositions;//to store all selected items position
public VocabCursorAdapter(Context context, Cursor c,int flags) {
super(context, c,0);
selectedItemsPositions = new ArrayList<>();
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
View view = LayoutInflater.from(context).inflate(R.layout.item_vocab, viewGroup, false);
CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);
box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
int position = (int) compoundButton.getTag();
if (b) {
//check whether its already selected or not
if (!selectedItemsPositions.contains(position))
selectedItemsPositions.add(position);
} else {
//remove position if unchecked checked item
selectedItemsPositions.remove((Object) position);
}
}
});
return view;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
//your other stuff
CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);
box.setTag(cursor.getPosition());
if (selectedItemsPositions.contains(cursor.getPosition()))
box.setChecked(true);
else
box.setChecked(false);
}
}
Try this
public class VocabCursorAdapter extends CursorAdapter {
private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>(); // array list for store state of each checkbox
public VocabCursorAdapter(Context context, Cursor c, int flags) {
for (int i = 0; i < c.getCount(); i++) { // c.getCount() return total number of your Cursor
itemChecked.add(i, false); // initializes all items value with false
}
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
...
final int position = cursor.getPosition(); // get position by cursor
CheckBox checkBox = (CheckBox) view.findViewById(R.id.editCheckbox);
checkBox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (itemChecked.get(position) == true) { // if current checkbox is checked, when you click -> change it to false
itemChecked.set(position, false);
} else {
itemChecked.set(position, true);
}
}
});
checkBox.setChecked(itemChecked.get(position)); // set the checkbox state base on arraylist object state
Log.i("In VocabCursorAdapter","position: "+position+" - checkbox state: "+itemChecked.get(position));
}
}
public class ObservationselectattributeFragment extends Fragment {
DatabaseHandler mDBHandler;
ListView mListView;
SimpleCursorAdapter mSCA;
Cursor mCsr;
ArrayList<String> attributeItems = new ArrayList<>();
public ObservationselectattributeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate the layout for this fragment
View view1=inflater.inflate(R.layout.fragment_observationselectattribute, container, false);
//Bundle bundle2 = getArguments();
Bundle bundle1 = getArguments();
final int firsttext= bundle1.getInt("TotalCount");
final String selectedtreatment= bundle1.getString("SelectedTreatment");
Toast.makeText(getActivity(),"value \n"+firsttext+"\n"+"treatment \n"+selectedtreatment, Toast.LENGTH_SHORT).show();
// Toast.makeText(getActivity(),"SelectedTreatment \n"+selectedtreatment, Toast.LENGTH_SHORT).show();
mListView = (ListView)view1.findViewById(R.id.lv001);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Button addattribute = (Button)view1.findViewById(R.id.addattribute);
addattribute.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String items1="";
Integer tcount1=0;
for(String item1:attributeItems){
items1+="-"+item1+"\n";
tcount1++;
}
Toast.makeText(getActivity(),"you have selected \n"+items1,Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(),"you have selected \n"+tcount1,Toast.LENGTH_LONG).show();
/*FragmentTransaction fr= getFragmentManager().beginTransaction();
fr.replace(R.id.main_container, new ShowObservationDataRecordingFragment()).addToBackStack("ObservationselectattributeFragment");
fr.commit();*/
Bundle bundle = new Bundle();
bundle.putInt("TotalCount2",firsttext);
bundle.putInt("TotalCount1", tcount1);
bundle.putString("SelectedTreatment", selectedtreatment);
Fragment showobservationdatarecordingfragment = new ShowObservationDataRecordingFragment();
showobservationdatarecordingfragment.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.main_container, showobservationdatarecordingfragment).addToBackStack("ObservationselectattributeFragment").commit();
}
});
mDBHandler = new DatabaseHandler(this.getActivity());
mCsr = mDBHandler.getAllRecords();
// Prepare a list of the columns to get the data from, for the ListViewt
String[] columns_to_get_data_from = new String[]{
DatabaseHandler.KEY_IDS,
DatabaseHandler.KEY_NAMES,
DatabaseHandler.KEY_FNAME,
DatabaseHandler.KEY_MONAME,
DatabaseHandler.KEY_SNAME
};
// Prepare a list of the Views into which to place the data
int[] itemviews_to_place_data_in = new int[]{
R.id.euserid,
R.id.eusername,
R.id.efname,
R.id.emoname,
R.id.esname
};
// get and instance of SimpleCursorAdapter
mSCA = new SimpleCursorAdapter(getActivity(),
R.layout.listviewitem_record,
mCsr,
columns_to_get_data_from,
itemviews_to_place_data_in,
0);
// Save the ListView state (= includes scroll position) as a Parceble
Parcelable state = mListView.onSaveInstanceState();
// get and instance of SimpleCursorAdapter the listviewitem_record layout
mListView.setAdapter(mSCA);
// Restore previous state (including selected item index and scroll position)
mListView.onRestoreInstanceState(state);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String attributeItem1 = ((TextView)view.findViewById(R.id.euserid)).getText().toString();
String attributeItem2 = ((TextView)view.findViewById(R.id.eusername)).getText().toString();
String attributeItem3 = ((TextView)view.findViewById(R.id.efname)).getText().toString();
String attributeItem4 = ((TextView)view.findViewById(R.id.emoname)).getText().toString();
String attributeItem5 = ((TextView)view.findViewById(R.id.esname)).getText().toString();
String attributeItem = attributeItem1 + attributeItem2 + attributeItem3 + attributeItem4 + attributeItem5;
// CheckedTextView box = (CheckedTextView) view.findViewById(R.id.record_checkbox);
// box.setChecked(true);
CheckedTextView checkedTextView = (CheckedTextView) view.findViewById(R.id.record_checkbox);
if(checkedTextView.isChecked()) {
checkedTextView.setChecked(false);
} else {
checkedTextView.setChecked(true);
}
if(attributeItems.contains(attributeItem)){
attributeItems.remove(attributeItem);//uncheck item
}
else
{
attributeItems.add(attributeItem);
}
Toast.makeText(getActivity(), "Item1 = " + attributeItem1 +"\n"+ "Item2 ="+attributeItem2 +"\n"+"Item3 ="+attributeItem3+"\n"+"Item4 ="+attributeItem4+"\n"+"Item5 ="+attributeItem5, Toast.LENGTH_SHORT).show();
}
});
((HomeActivity) getActivity())
.setActionBarTitle("Select Attribute");
return view1;
}
}
I have a listView generated from a database, is there a way to make a background colour or a picture to each "section" in the list:
if the first symbol in "Tip" is "W" the background should be Green, and if its "L" it should be red
Im thinking something like this, but i have no idea where to put it since it have to be done in every section:
tipvalue = BetsDbAdapter.KEY_TIP;
//Here to split the value to gain only "W" or "L"
String arrtip[] = tipvalue.split(" ", 2);
temptip = arrtip[0];
//then set background
if (temptip.equals("W")) {
getWindow().getDecorView().setBackgroundColor(Color.GREEN);
To the left is my listView and right is the xml file to make each "section" in the listview
Here is my database:
This is code generating the listView
public class StoredBets extends Activity {
private BetsDbAdapter dbHelper;
private SimpleCursorAdapter dataAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.results);
dbHelper = new BetsDbAdapter(this);
dbHelper.open();
}
#Override
public void onStart(){
super.onStart();
displayListView();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.results, menu);
return true;
}
public void testknap1(View v) {
Intent myIntent = new Intent(StoredBets.this, Overview.class);
startActivity(myIntent);
}
private void displayListView() {
Cursor cursor = dbHelper.fetchAllStats();
String[] columns = new String[] {
BetsDbAdapter.KEY_SMATCH,
BetsDbAdapter.KEY_TIP,
BetsDbAdapter.KEY_BETAMOUNT,
BetsDbAdapter.KEY_BODDS
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.smatch,
R.id.tip,
R.id.bodds,
R.id.betamount,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.storedbets,
cursor,
columns,
to,
0);
ListView listView = (ListView) findViewById(R.id.listView2);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the state's capital from this row in the database.
String betMatch =
cursor.getString(cursor.getColumnIndexOrThrow("smatch"));
Toast.makeText(getApplicationContext(),
betMatch, Toast.LENGTH_SHORT).show();
Intent myIntent = new Intent(StoredBets.this, SetWinVoidLoss.class);
myIntent.putExtra("id", id);
startActivity(myIntent);
}
});
}
}
EDIT 2:
#amal
This is the layout(results.xml) with the listview
<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=".StoredBets" >
<ListView
android:id="#+id/listView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/textView1"
android:layout_alignTop="#+id/button1" >
</ListView>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="180dp"
android:onClick="testknap1"
android:text="Button" />
</RelativeLayout>
you can get a fair idea from my code,
code snippet for displaying ListViews where the "curSelected" item has a different background:
final ListView lv = (ListView)findViewById(R.id.lv);
lv.setAdapter(new BaseAdapter()
{
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = new TextView(ListHighlightTestActivity.this);
convertView.setPadding(10, 10, 10, 10);
((TextView)convertView).setTextColor(Color.WHITE);
}
convertView.setBackgroundColor((position == curSelected) ?
Color.argb(0x80, 0x20, 0xa0, 0x40) : Color.argb(0, 0, 0, 0));
((TextView)convertView).setText((String)getItem(position));
return convertView;
}
public long getItemId(int position)
{
return position;
}
public Object getItem(int position)
{
return "item " + position;
}
public int getCount()
{
return 20;
}
});
This is a tutorial of how to write an adapter for a list view. amal is right, you can change the separate items in the list view in the getView() method.
I've been having a lot of trouble with this problem. I have a listview that contains:
ImageView / contactName / TextView / CheckBox
The contactName in the listview is populated by reading the contacts on the phone from a SimpleCursorAdapter. All for elements show when the app runs, but the problem I'm having is connecting the checkboxes to their corresponding item in the list.
Through some research, I found that I must use a getView() to link the checkboxes with the items in the list, but through practice, I can't seem to get it to work right. Furthermore, none of the examples I've tried really explained how to apply getView(). The most full example I've been working from is from here:
http://androidcocktail.blogspot.com/2012/04/adding-checkboxes-to-custom-listview-in.html
The twist is that this reads and populates my listview with my contacts:
private void populateContactList() {
// Build adapter with contact entries
Cursor cursor = getContacts();
String[] fields = new String[] {
ContactsContract.Data.DISPLAY_NAME
};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
fields, new int[] {R.id.contactEntryText});
lv.setAdapter(adapter);
} // END POPULATECONTACTLIST
private Cursor getContacts()
{
// Run query
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
(chkboxAllVisible ? "0" : "1") + "'";
String[] selectionArgs = null;
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
} // END GETCONTACTS
How do I link each checkbox to the a corresponding contact items in my listview?
Ok i have created a test project for you try to understand code if any problem you are having then ask I will try to help you...
HERE IS MY ONCREATE FUNCTION OF ACTIVITY.
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<String> elements = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
elements.add("elements " + i);
}
CheckBox master_cb = new CheckBox(getApplicationContext());
master_cb.setText("Check All");
//HERE IS THE LIST VIEW WHICH I HAVE CREATED IN MY XML FILE.
ListView lv = (ListView) findViewById(R.id.listView1);
//HERE I AM CREATING CUSTOM ADAPTER OBJECT.
my_custom_adapter adapter = new my_custom_adapter(this, android.R.layout.simple_list_item_1, elements);
lv.addHeaderView(master_cb);
lv.setAdapter(adapter);
master_cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Intent my_intent = new Intent("master_check_change");
my_intent.putExtra("check_value", isChecked);
sendBroadcast(my_intent);
}
});
}
HERE IS MY CUSTOM ADAPTER.
public class my_custom_adapter extends ArrayAdapter<String> {
private Context context = null;
ArrayList<String> elements = null;
private ArrayList<Boolean> itemChecked = null;
public my_custom_adapter(Context context, int type, ArrayList<String> elements)
{
super(context, type, elements);
this.elements = elements;
this.context = context;
itemChecked = new ArrayList<Boolean>();
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("master_check_change")) {
boolean check_value = intent.getBooleanExtra("check_value", false);
set_checked(check_value);
notifyDataSetChanged();
}
}
};
context.registerReceiver(receiver, new IntentFilter("master_check_change"));
set_checked(false);
}
// AS EVERY TIME LISTVIEW INFLATE YOUR VIEWS WHEN YOU MOVE THEM SO YOU NEED TO SAVE ALL OF YOUR CHECKBOX STATES IN SOME ARRAYLIST OTHERWISE IT WILL SET ANY DEFAULT VALUE.
private void set_checked(boolean is_checked)
{
for (int i=0; i < elements.size(); i++) {
itemChecked.add(i, is_checked);
}
}
//THIS IS SIMPLY A CLASS VIEW WILL HOLD DIFFERENT VIEWS OF YOUR ROW.
static class ViewHolder
{
public TextView tv;
public CheckBox cb;
public ImageView iv;
}
#Override
public View getView (final int position, View convertView, ViewGroup parent)
{
View rowView = convertView;
ViewHolder holder = null;
if (rowView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
// HERE I AM INFLATING LISTVIEW LAYOUT.
rowView = inflater.inflate(R.layout.inflated_layout, null, false);
holder = new ViewHolder();
holder.cb = (CheckBox) rowView.findViewById(R.id.checkBox1);
holder.tv = (TextView) rowView.findViewById(R.id.textView1);
holder.iv = (ImageView) rowView.findViewById(R.id.imageView1);
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
}
if (holder != null) {
holder.tv.setText(elements.get(position));
holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
itemChecked.set(position, isChecked);
}
});
if(position < itemChecked.size()) {
holder.cb.setChecked(itemChecked.get(position));
}
}
return rowView;
}
}
main.xml file is this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</RelativeLayout>
inflated_layout code is :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<CheckBox
android:id="#+id/checkBox1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="17dp" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toLeftOf="#+id/checkBox1"
android:layout_toRightOf="#+id/imageView1"
android:singleLine="true"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
if you want to use string array instead of arraylist then replace
String[] elements = new String[10];
for (int i = 0; i < 10; i++) {
elements[i] = "elements " + i;
}
// IN YOUR CUSTOM ADAPTER CUNSTRUCTOR
public my_custom_adapter(Context context, int type, String[] elements)
and some more changes accordingly
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
fields, new int[] {R.id.contactEntryText});
See in this particular code you are only mapping text source (in field ) with actual textView (R.id.contactEntryText)... So similarly you need to add... another field and corresponding view to map for Checkbox.
or better make a CustomAdapter, you can find tutorials on that and override getView method,you get maximum flexibility.You can do whatever you want to do.
This might help: http://windrealm.org/tutorials/android/listview-with-checkboxes-without-listactivity.php
don,t go with custom list view you can use default listview having the facility of check boxes but only one with each list item read listview on android developer site for list view property. listview having checkbox you just need to set multiselection list view
Edit 1:
follow the link : click here
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, GENRES));
final ListView listView = getListView();
listView.setItemsCanFocus(false);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
Hi i've got a custom listview with a text view and a button in each row.
Im having trouble trying to use the buttons . Each button will fire a different intent. This is the xml file for the list view rows.
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
android:id="#+id/widget28"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<Button
android:id="#+id/widget29"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Remind me"
android:layout_alignParentRight="true"
/>
<TextView android:id="#+id/text12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff99ccff"
android:text="Text view" />
</RelativeLayout>
Then i have another xml file which simply contains the list view in a linear layout.
This is my custom array class.
public class customArray extends ArrayAdapter<String> {
int resource;
public customArray(Context cont, int _resource, List<String> items) {
super (cont, _resource,items);
resource = _resource;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
RelativeLayout rl;
String prod = getItem(position);
if (convertView == null) {
rl = new RelativeLayout(getContext());
LayoutInflater vi = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
vi.inflate(resource, rl, true);
} else {
rl = (RelativeLayout)convertView;
}
TextView t1 = (TextView)rl.findViewById(R.id.text12);
t1.setText(prod);
Button b1 = (Button)rl.findViewById(R.id.widget29);
return rl;
}
}
Then the final class which gets the data from a database and uses the custom adapter to display the information. Does anyone know how i would call each button?
`public class SatMain extends Activity {
/** Called when the activity is first created.
* #param cont */
#Override
public void onCreate(Bundle savedInstanceState)
{
List<String> results = new ArrayList<String>();
super.onCreate(savedInstanceState);
setContentView(R.layout.satmain);
dbAdapter db = new dbAdapter(this);
// button.setOnClickListener(m);
//---get all titles---
db.open();
db.InsertData();
Cursor c = db.getSat1();
if (c.moveToFirst())
{
do {
String pub = c.getString(c.getColumnIndex(db.KEY_Artist));
String pub1 = c.getString(c.getColumnIndex(db.KEY_Time));
results.add(pub + pub1 );
} while (c.moveToNext());
}
db.close();
ListView listProducts;
customArray ca = new customArray(this, R.layout.button, results);
listProducts = (ListView)findViewById(R.id.list1);
listProducts.setAdapter(ca);
ca.notifyDataSetChanged();
}
}`
In the "getView" method of your adapter, you should set an onClick listener for the button. You can do an anonymous class so that you can refer to the contents of the row in the button. I.e, add the following where you get b1 in your example.
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//create activity based on prod
}
});