Fragment Context Menu Notify Adapter - android

I have a ListView within a Fragment. I have been trying to setup a functional ContextMenu to delete and edit entries. Simply passing saveAdapter.notifyDataSetChanged(); returns null. Passing ArrayAdapter<LiftSave> saveAdapter = new SaveListAdapter(); results in a message:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes.
I'd greatly appreciate any insight into resolving the adapter, and/or any advice to the best practice for the of setup the edit option. Perhaps launching a custom AlertDialog? Thanks in advance.
Fragment:
public static class FragmentS extends Fragment {
private ListView saveListView;
private List<LiftSave> LiftSaves = new ArrayList<LiftSave>();
private static final int EDIT = 0, DELETE = 1;
int longClickedItemIndex;
DatabaseHandler dbHandler;
ArrayAdapter<LiftSave> saveAdapter;
public FragmentS() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.listview_s,
container, false);
saveListView = (ListView) rootView.findViewById(R.id.saveListView);
registerForContextMenu(saveListView);
DatabaseHandler dbHandler;
dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
if (dbHandler.getLiftSavesCount() != 0)
LiftSaves.addAll(dbHandler.getAllLiftSaves());
populateList();
saveListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickedItemIndex = position;
return false;
}
});
return rootView;
}
private void populateList() {
ArrayAdapter<LiftSave> saveAdapter = new SaveListAdapter();
saveListView.setAdapter(saveAdapter);
}
public class SaveListAdapter extends ArrayAdapter<LiftSave> {
public SaveListAdapter() {
super(getActivity(), R.layout.listview_item, LiftSaves);
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null)
view = getActivity().getLayoutInflater().inflate(R.layout.listview_item, parent, false);
LiftSave currentLiftSave = LiftSaves.get(position);
TextView liftName = (TextView) view.findViewById(R.id.liftName);
liftName.setText(currentLiftSave.getLiftName());
TextView maxValue = (TextView) view.findViewById(R.id.maxValue);
maxValue.setText(currentLiftSave.getMaxValue());
TextView weightAndReps = (TextView) view.findViewById(R.id.weightAndReps);
weightAndReps.setText(currentLiftSave.getRepsAndWeight());
TextView liftNotes = (TextView) view.findViewById(R.id.liftNotes);
liftNotes.setText(currentLiftSave.getLiftNotes());
TextView date = (TextView) view.findViewById(R.id.todayDate);
date.setText(currentLiftSave.getTodayDate());
return view;
}
}
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
menu.setHeaderIcon(R.drawable.pencil_icon);
menu.setHeaderTitle("Save Options");
menu.add(Menu.NONE, EDIT, menu.NONE, "Edit Save");
menu.add(Menu.NONE, DELETE, menu.NONE, "Delete Save");
}
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case EDIT:
// TODO: Add save edit code
break;
case DELETE:
dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
dbHandler.deleteLiftSave(LiftSaves.get(longClickedItemIndex));
LiftSaves.remove(longClickedItemIndex);
saveAdapter.notifyDataSetChanged();
break;
}
return super.onContextItemSelected(item);
}
}
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"
tools:context=".TabbedActivity$FragmentS"
android:background="#android:color/holo_blue_dark">
<LinearLayout
android:id="#+id/tabSaveList"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Saved Maxes"
android:id="#+id/textView"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:textColor="#fffaf4a1"
android:textStyle="bold" />
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/saveListView" />
</LinearLayout>
</RelativeLayout>

change int longClickedItemIndex; to be LiftSave longClickedItemLiftSave;
Then in the long press listener capture that value as longClickedItemLiftSave:
saveListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
longClickedItemLiftSave = (LiftSave) parent.getItemAtPosition(position);
return false;
}
});
then in your menu handling just call ArrayAdapter#remove(T), this will call notifyDataSetChanged for you
case DELETE:
dbHandler = new DatabaseHandler (getActivity().getApplicationContext());
dbHandler.deleteLiftSave(longClickedItemLiftSave);
saveAdapter.remove(longClickedItemLiftSave);
break;
finally, change your populateList so it uses the fragment's field of saveAdapter instead of a local var to this method only.
private void populateList() {
saveAdapter = new SaveListAdapter();
saveListView.setAdapter(saveAdapter);
}

Related

setText not working on Views acquired from ArrayListAdapter

I am trying to manipulate a View in an ArrayList adapter. I am using the following code:
for (int i = 0; i < listView.getCount(); i++){
TextView busDestTextView = (TextView) busAdapter.getView(i, null, null).findViewById(R.id.busDestinations);
TextView busNumberTextView = (TextView) busAdapter.getView(i, null, null).findViewById(R.id.busNumber);
if (dataSnapshot.getKey().equals(busDestTextView.getText().toString())){
busNumberTextView.setText(dataSnapshot.getValue().toString());
break;
}
}
The listView consist of horizontal Views having two text views busDestinations and busNumber.
The setText() method is not changing the text in desired way. It seems to have no effect on the busNumberTextView.
EDIT: As other users suggested, these are the codes I have right now.
MainActivity.java
package com.example.busnotifier;
import ...;
public class MainActivity extends AppCompatActivity {
private FirebaseDatabase mFirebaseInstance;
private DatabaseReference mFirebaseDatabase;
private FirebaseMessaging mFirebaseMessaging;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ArrayList<Bus> buses = new ArrayList<Bus>();
buses.add(new Bus("Dev_Guradiya~Industry_House~Palasia", 0));
buses.add(new Bus("Bhavarkua-V", 0));
buses.add(new Bus("Boys_hostel~teen_imli~Khajarana", 0));
buses.add(new Bus("Khativala~Rani_Sati~Agnibaan~Khajrana", 0));
buses.add(new Bus("Kalani_Naga", 0));
buses.add(new Bus("Khandwa_naka~Shalimaar~Scheme_54", 0));
buses.add(new Bus("tilak_nagar", 0));
buses.add(new Bus("Rani_Sati~Agnibaan~Khajrana~Rani_sati", 0));
buses.add(new Bus("Industry_House~Rani_Sati~Agnibaan~Khajrana", 0));
buses.add(new Bus("Agnibaan~Khajarana~Rani_Sati", 0));
buses.add(new Bus("PardesipuraVijaynagar", 0));
buses.add(new Bus("Sai_Mandir~VijayNagar", 0));
BusAdapter busAdapter= new BusAdapter(this, buses);
// Get a reference to the ListView, and attach the adapter to the listView.
final ListView listView = (ListView) findViewById(R.id.busListView);
listView.setAdapter(busAdapter);
mFirebaseInstance = FirebaseDatabase.getInstance();
mFirebaseInstance.getReference("Buses").addChildEventListener(new ChildEventListener() {
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
for (int i = 0; i < listView.getCount(); i++){
if (dataSnapshot.getKey().equals(buses.get(i).getDestinations())){
TextView busNumberTextView = (TextView) listView.getChildAt(i).findViewById(R.id.busNumber);
busNumberTextView.setText(dataSnapshot.getValue().toString());
}
}
Toast.makeText(getApplicationContext(), ""+dataSnapshot.getKey(), Toast.LENGTH_SHORT).show();
}
});
}
}
BusAdapter.java
package com.example.busnotifier;
import ....;
public class BusAdapter extends ArrayAdapter<Bus> {
private FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
private DatabaseReference mDatabaseReference = mFirebaseDatabase.getReference("Buses");
public BusAdapter(Activity context, ArrayList<Bus> buses){
super(context, 0, buses);
}
public View getView(int position, View convertView, ViewGroup parent){
View busListItemView = convertView;
if(busListItemView == null) {
busListItemView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}
// TextView for the Bus number
Bus currentBus = getItem(position);
final TextView busNumberTextView = (TextView) busListItemView.findViewById(R.id.busNumber);
busNumberTextView.setText(String.valueOf(currentBus.getBusNumber()));
// Used EraserRegular font for the bus-stop names
Typeface typeFace = Typeface.createFromAsset(getContext().getAssets(), "fonts/KGSecondChancesSolid.ttf");
busNumberTextView.setTypeface(typeFace);
// TextView for the destinations of the corresponding bus-number
final Button destinationsTextView = (Button) busListItemView.findViewById(R.id.busDestinations);
destinationsTextView.setText(currentBus.getDestinations());
destinationsTextView.setTypeface(typeFace);
destinationsTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*If the user clicks on a button it will change color and subscribe
the user to corresponding Topic of the FireBase*/
Toast.makeText(getContext(), "Subscribed to: "+destinationsTextView.getText(), Toast.LENGTH_LONG).show();
int color = ContextCompat.getColor(getContext(), R.color.buttonClicked);
destinationsTextView.setBackgroundColor(color);
FirebaseMessaging.getInstance().subscribeToTopic(String.valueOf(destinationsTextView.getText().toString()));
mDatabaseReference.child(destinationsTextView.getText().toString()).setValue(Integer.parseInt(busNumberTextView.getText().toString()));
Log.d(">>>>", "onClick: "+destinationsTextView.getText().toString()+"/"+busNumberTextView.getText().toString());
}
});
return busListItemView;
}
}
ListItem.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="horizontal"
android:layout_width="match_parent"
android:padding="5dp"
android:gravity="center"
android:background="#414141"
android:id="#+id/busListEntry"
android:layout_height="wrap_content">
<Button
android:layout_width="0dp"
android:id="#+id/busDestinations"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_weight="5"
android:background="#color/buttonColor"
android:textColor="#fff"
android:paddingLeft="5dp"
android:textAllCaps="false"
android:layout_marginRight="10dp"
tools:text="aksjfdkaskdfalsasfasfasfasdasf aslkjfaksjfkjaks dkajsdf asdfajsdfjalksd fasjflkajsdasf asjfkajsdklfjas"
android:textSize="17sp"/>
<TextView
android:layout_width="wrap_content"
android:id="#+id/busNumber"
android:textStyle="bold"
android:textSize="17sp"
android:textColor="#fff"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#drawable/round_background"
tools:text="1"/>
Bus.java
package com.example.busnotifier;
public class Bus {
private int busNumber;
private String destinations;
public Bus(String destinations, int busNumber) {
this.busNumber = busNumber;
this.destinations = destinations;
}
public int getBusNumber() {
return busNumber;
}
public String getDestinations() {
return destinations;
}
public void setDestinations(String destinations) {
this.destinations = destinations;
}
public void setBusNumber(int busNumber) {
this.busNumber = busNumber;
}
}
You have 2 approaches. 1 you can use listview with onItemClickListener. The alternative is to implement OnItemSelectedListener in your bus array adapter.
I'm a little rusty with android so here is what I recommend:
Get your list view and adapter setup:
mAdapter = new BusAdapter();
mListView = (ListView) findViewById(R.layout.my_listview);
mListView.setAdapter(mAdapter);
Add item click listener to your list view:
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView parent, View view,int position, long id) {
mAdapter.onBusItemSelected(position);
Log("Selected item at position " + position);
mAdapter.notifyDataSetChanged()
}
});
In your adapter, add a public function called "onBusItemSelected(int position)" and update your data structures. For example, have a boolean variable labeled "selected". By default it is false.
...
void onItemSelected(int position) {
getItem(position).selected = true;
}
Last, your custom ArrayAdapter needs to update the getView() item to look for the new variable and update the text color based on that variable.
public View getView(int position, View convertView, ViewGroup parent)
...
if (bus.selected) {
holder.textView.setTextColor(RED);
} else {
holder.textView.setTextColor(BLACK);
}
...
}
I think you put ViewGroup null in busAdapter.getView(i, null, null). You can read: https://developer.android.com/reference/android/widget/Adapter.html#getView(int, android.view.View, android.view.ViewGroup)

Maintaining checkbox states in listview with CursorAdapter

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;
}
}

How to display checkbox on every entry in a listView

From this Activity i get text from textField and display it in a ListView.
Now i want to to add check box on every entry in a listView Cell and also like to know how to display more than one text in a single ListView Cell.
Help with code will be appreciated.
Here is my code ....
public class AfterRegister extends AppCompatActivity
{
ListView listView;
EditText editText;
Button insertItemButton;
ArrayList<String> arrayList = new ArrayList<String>();
ArrayAdapter<String> adapter;
CheckBox checkBox;
StoreRegistrationDataBase storeRegistrationDataBase;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_after_register);
storeRegistrationDataBase = new StoreRegistrationDataBase(this);
storeRegistrationDataBase = storeRegistrationDataBase.open();
checkBox = (CheckBox) findViewById(R.id.checkbox);
insertItemButton = (Button) findViewById(R.id.button4);
insertItemButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
editText = (EditText) findViewById(R.id.editText2);
listView = (ListView) findViewById(R.id.listView);
String getEditTextString = editText.getText().toString();
if(isAlphaNumeric(getEditTextString))
{
if(!getEditTextString.equals(""))
{
arrayList.add(getEditTextString);
adapter = new ArrayAdapter<String>(getBaseContext(), R.layout.text_view_layout, R.id.achView1, arrayList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
editText.setText("");
}
else
{
Toast.makeText(AfterRegister.this, "You can not insert empty field", Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(AfterRegister.this, "Remove Space", Toast.LENGTH_SHORT).show();
}
}
});
listView.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
return false;
}
});
}
public boolean isAlphaNumeric(String s)
{
String pattern= "^[a-zA-Z0-9]*$";
if(s.matches(pattern))
{
return true;
}
return false;
}
}
You have to use a BaseAdapter and some Getter/Setter methods to add multiple texts/images/other UI elements in each item of your list view.
You have to implement multiple things to get this result. Here they are --
Create a Custom Layout for each item of your ListView.
listview_item_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/layout_textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_marginRight="5dip"
android:textStyle="bold"/>
<TextView
android:id="#+id/layout_textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_marginLeft="5dip"
android:textStyle="bold"/>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/checkbox"
android:text="Test"/>
</LinearLayout>
Create a custom class and add some Getter/Setter methods.
ListRowItem.java
public class ListRowItem implements Serializable{
String carrier,number;
public String getCarrier(){
return carrier;
}
public String getNumber(){
return number;
}
public void setCarrier(String ba_carrier){
carrier = ba_carrier;
}
public void setNumber(String ba_number){
number = ba_number;
}
}
Create a custom class and extend the BaseAdapter class.
public class MyBaseAdapter extends BaseAdapter {
public Context ba_context;
public ArrayList<ListRowItem> listitem = new ArrayList<>();
public LayoutInflater inflater;
ListRowItem currentlistitem;
public MyBaseAdapter(Context ma_context, ArrayList<ListRowItem> ma_listitem) {
super();
this.ba_context = ma_context;
this.listitem = ma_listitem;
inflater = (LayoutInflater) ba_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return this.listitem.size();
}
#Override
public Object getItem(int position) {
return this.listitem.get(position);
}
#Override
public long getItemId(int position) {
return (long) position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.listview_item_layout, parent, false);
TextView carrier = (TextView) vi.findViewById(R.id.layout_textview1);
TextView number = (TextView) vi.findViewById(R.id.layout_textview2);
currentlistitem = listitem.get(position);
String str_carrier = currentlistitem.getCarrier();
String str_number = currentlistitem.getNumber();
carrier.setText(str_carrier);
number.setText(str_number);
return vi;
}
}
Finally, populate your ArrayList and set the Adapter in your MainActivity.
ArrayList<ListRowItem> listitem = new ArrayList<>();
Context context = TestActivity.this;
MyBaseAdapter baseAdapter;
ListRowItem lr = new ListRowItem();
lr.setNumber(number);
lr.setCarrier(carrier);
listitem.add(lr);
baseAdapter = new MyBaseAdapter(context,listitem);
setContentView(R.layout.activity_test);
listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(baseAdapter);
Hope this helps!!

ListView in a fragment Clickable and on item clicked listener

I have a listview in a fragment here is my current code for it:
public static class AllSectionFragment extends Fragment {
public static final String ARG_SECTION_NUMBER = "section_number";
public AllSectionFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tasks_all,
container, false);
// /////////////////////////////////////////////////////////////////
// Set up all components here:: ie text views , buttons lists etc.//
// that correspond to the layout fragment xml file //
////////////////////////////////////////////////////////////////////
TextView dummyTextView = (TextView) rootView
.findViewById(R.id.fragment_tasks_all_textView);
dummyTextView.setText(Integer.toString(getArguments().getInt(
ARG_SECTION_NUMBER)));
ArrayList<String> arrayList = new ArrayList<String>();
ListView allList = (ListView) rootView
.findViewById(R.id.fragment_tasks_all_list);
MyCustomAdapter mAdapter = new MyCustomAdapter(getActivity(),
arrayList); // Class to populate a ListView with an
// ArrayList
allList.setAdapter(mAdapter);
// Populate array list
for (int i = 0; i < 5; i++) {
arrayList.add(" All Task " + i);
}
mAdapter.notifyDataSetChanged();
return rootView;
}
public void onListItemClick(ListView l, View v, int position, long id) {
System.out.println("pos: "+ position);
}
}
and my layout.xml file
<LinearLayout 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:orientation="vertical"
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=".TasksActivity$DummySectionFragment" >
<TextView
android:id="#+id/fragment_tasks_all_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ListView
android:id="#+id/fragment_tasks_all_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="0.41"
android:cacheColorHint="#00000000"
android:clickable="true"
android:listSelector="#android:color/transparent"
android:transcriptMode="alwaysScroll" >
</ListView>
First of all. how can i make it so that i can click on an item in the list,
and second of all how do i add the onclick listener for it.
Why dont you just use ListFragment:
public static class ArrayListFragment extends ListFragment {
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, Shakespeare.TITLES));
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.i("FragmentList", "Item clicked: " + id);
}
}
Use the alternative constructor for ArrayAdapter that allows you to specify a layout file to host your listview:
public ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects)
I had a similar issue and was resolved by creating a interface with onClick method and implementing it in fragment.
Try do this:
Create a interface:
MyOnViewClickListener.java
public interface MyOnViewClickListener {
public void myOnViewClickListener(View v);
}
In your custom adapter class, create a constructor passing MyOnViewClickListener as argument:
private Context context;
private MyOnViewClickListener itemListener;
private List<String> items;
public MyCustomAdapter(Context context, List<String> items, MyOnViewClickListener itemListener) {
this.itemListener = itemListener;
this.context = context;
this.items = items;
}
Inside getView() method, put:
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.your_row_layout, parent, false);
TextView textView1 = (TextView) row.findViewById(R.id.quizchallenge);
textView1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
itemListener.myOnViewClickListener(v);
}
});
Finally, in your fragment class, implement the new interface:
public class ListFriendFragment extends Fragment implements MyOnViewClickListener {
.
.
.
#Override
public void myOnViewClickListener(View v){
//call your method
quickQuiz();
}
Set up the adapter:
adapter = new MyCustomAdapter(getContext(), myItemsList, MyFragment.this);

BaseAdapter and ContextMenu

Hello stackoverflow community,
Basically, i have gallery displaying some images using a gridView + imageView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<GridView android:id="#+id/PhoneImageGrid"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:numColumns="auto_fit" android:verticalSpacing="12dp"
android:horizontalSpacing="12dp" android:columnWidth="90dp"
android:stretchMode="columnWidth" android:gravity="center" />
<ImageView android:id="#+id/thumbImage" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_centerInParent="true"
android:scaleType="centerCrop"
/>
I would like to use setOnLongClick for each imageView displayed by the adapter.
This works well, however, when clicking long on the imageView, i would like to display a ContextMenu with some items ( i.e, you long click on an imageView, a contextMenu is displayed with some items : Image information, send this image ...).
Unfortunatly, i can't figure out how to inflate this menu in the adapter.(Probably not the good way to do it )
I have the following lines in my main activity
_adapter = new ImageAdapter(activity,storedObjects.getAlbums());
imagegrid.setAdapter(_adapter);
My adapter ( some useless lines removed )
public class ImageAdapter extends BaseAdapter {
private Albums albums;
private Context context;
private LayoutInflater inflater;
public ImageAdapter(Context context, Albums albums) {
this.albums = albums;
this.context = context;
inflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE);
if(albums.getAlbumsListSize() == 0) {
Toast.makeText(context, "There is no album to display", Toast.LENGTH_LONG).show();
}
}
public View getView(final int position, View view, ViewGroup parent) {
ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(R.layout.galleryitem, null);
holder.imageview = (ImageView) view.findViewById(R.id.thumbImage);
holder.checkbox = (CheckBox) view.findViewById(R.id.itemCheckBox);
holder.textview = (TextView) view.findViewById(R.id.album_name);
holder.checkbox.setChecked(true);
//Bitmap loadingBM = BitmapFactory.decodeResource(context.getResources(),R.drawable.loading_image);
//holder.imageview.setImageBitmap(loadingBM);
view.setTag(holder);
}
else {
holder = (ViewHolder) view.getTag();
}
holder.imageview.setClickable(true);
holder.imageview.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
Log.v(TAG,"onLongClick ok !");
return false;
}
});
imageDownloader.download(this.context, albums.getAllAlbums().get(position).getThumbnailUri(), holder.imageview);
return view;
}
Questions :
setOnLongClickListener works properly, when i click on an image, my Log is displayed in logcat, however, how to create a menu for each imageView ?
Apparently, i can only override onCreateContextMenu in my main activity. I guess i could pass each ImageView to onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) but how ?
I would be really grateful if you could help me out with this.
Thank you very much
Florent Valdelievre
Instead of setOnLongClickListener on the ImageView, call registerForContextMenu with your GridView. Then, implement onCreateContextMenu and onContextItemSelected.
Here is a simple ListActivity to show you how it works.
public class GreetingActivity extends ListActivity {
private static final String[] mGreetings = { "Hello", "Goodbye" };
private static final String[] mPeople = { "Alice", "Bob", "Charlie" };
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mPeople);
setListAdapter(adapter);
ListView listView = getListView();
registerForContextMenu(listView);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
for (int i = 0; i < mGreetings.length; ++i) {
String greeting = mGreetings[i];
menu.add(v.getId(), i, ContextMenu.NONE, "Say " + greeting);
}
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo menuInfo
= (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int adapterPosition = menuInfo.position;
String person = mPeople[adapterPosition];
int menuItemId = item.getItemId();
String greeting = mGreetings[menuItemId];
String msg = String.format("%s, %s!", greeting, person);
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
return true;
}
}
Thank you so much #chiuki, it works as expected
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
final GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
registerForContextMenu(imagegrid);
storedObjects.storeThumbnailsURI();
_adapter = new ImageAdapter(activity,storedObjects.getAlbums());
imagegrid.setAdapter(_adapter);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
Log.v("context menu","context menu");
menu.setHeaderTitle("Context Menu");
menu.add(0, START_SLIDESHOW_ON_THIS_ALBUM, 0, "Start SlideShow for this Album");
menu.add(0, DOWNLOAD_WHOLE_ALBUM, 0, "Download this Album");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case START_SLIDESHOW_ON_THIS_ALBUM:
selectThisAlbumOnly(info);
startSlideShow();
break;
case DOWNLOAD_WHOLE_ALBUM:
break;
}
return true;
}
In the Adapter, make sure you don't have any setClickable = true
Cheers
Florent

Categories

Resources