I've created a ListView that in each row has a button with UP and DOWN arrow. Pressing these buttons makes the row to be shifted one position up or down.
I've achieved it by implementing OnClickListener for both buttons in a the override method getView. It works as it should however I fill bad with that cuz it seems to be highly memory consuming and lots of code is doubled.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView = inflater.inflate(R.layout.row_layout, parent, false);
TextView textView = (TextView) rowView.findViewById(R.id.label);
CheckBox checkBox = (CheckBox) rowView.findViewById(R.id.checkbox);
checkBoxes.add(position, checkBox);
String address = this.getItem(position).getAddress();
String tokenizedAddress = tokenizeAddress(address);
textView.setText(tokenizedAddress);
ImageButton buttonUp = (ImageButton)rowView.findViewById(R.id.button_up);
ImageButton buttonDown = (ImageButton)rowView.findViewById(R.id.button_down);
buttonUp.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ListAdapter adapter = ListAdapter.this;
if(position != 0 ){
GameTask current = adapter.getItem(position);
ArrayList<GameTask> list = new ArrayList<GameTask>();
for( int i = 0; i < adapter.getCount(); i++ )
list.add(adapter.getItem(i));
list.remove(position);
list.add(position-1, current);
adapter.clear();
for( int i = 0; i < list.size(); i++ ){
adapter.add(list.get(i));
}
adapter.notifyDataSetChanged();
}
}
});
buttonDown.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ListAdapter adapter = ListAdapter.this;
if(position != adapter.getCount()-1 ){
GameTask current = adapter.getItem(position);
ArrayList<GameTask> list = new ArrayList<GameTask>();
for( int i = 0; i < adapter.getCount(); i++ )
list.add(adapter.getItem(i));
list.remove(position);
list.add(position+1, current);
adapter.clear();
for( int i = 0; i < list.size(); i++ ){
adapter.add(list.get(i));
}
adapter.notifyDataSetChanged();
}
}
});
return rowView;
}
Both listeners do almost the same, the only difference is the condition and the value of shifting +1/-1. I was wondering about creating the inner class implementing OnClickListener in the extended ArrayAdapter class however, I have no idea, how I could then pass the position of the row clicked to this inner class.
Instead of adding and removing elements from your ArrayList, you can better implement Collections.swap(List list, int firstElementIndex, int secondElementIndex) it would be much easier as you don't have to iterate through the whole Collection. A simple example for the same can be found here.
You could make a method that would be used by both buttonUp and buttonDown. This method could take as a parameter the type of action that was pressed (UP/DOWN), and the position of item in ListView, and then call this method in both of your click listener passing the appropriate action.
Example:
// 2 new constants
private static final int UP = 0;
private static final int DOWN = 1;
// Based on "type", increment or decrement the position.
private void changeRow(int type, int position){
if(type==UP){
position=position-1;
}else if(type==DOWN){
position=position+1;
}
// ........
// Then in your "for" cicle you specify:
list.add(position, current);
// ........
}
Then in the onClick() method of buttonUp you specify:
changeRow(UP, position);
and for buttonDown:
changeRow(DOWN, position);
This can be easily achieved
The way to do this is to store the data to be displayed in an List
Then when the user clicks the up or down arrow
Swap the references of data items which are shifting position using Collections.swap(List, int, int)
Then call notifyDataSetChanged on the adapter
Related
I am a noob android studio and this is my first app I am developing.
Context: I have a ListView lv which is populated with CheckedTextViews using a ListAdapter.
ListAdapter adapter = new SimpleAdapter(
c, manageTrackers.trackers,
R.layout.list_item, new String[]{"id", "mobile", "status"},
new int[]{R.id.trackerID, R.id.trackerMobile, R.id.trackerStatus});
lv.setAdapter(adapter);
I have set up the OnItemClickListener for lv as shown below which checks and unchecks the check boxes as expected. I want the checks to remain persistent when I navigate between activities, so I am storing a key in the selectedTrackers array list.
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
{
CheckedTextView ctv = (CheckedTextView) view.findViewById(R.id.trackerID);
HashMap s = (HashMap)lv.getItemAtPosition(i);
String mob = (String)s.get("mobile");
//checked and pressed
if (ctv.isChecked())
{
ctv.setChecked(false);
for (int j = 0; j < selectedTrackers.size(); j++)
{
if (selectedTrackers.get(j) == mob)
{
selectedTrackers.remove(j);
break;
}
}
}
//not checked
else
{
ctv.setChecked(true);
selectedTrackers.add(mob);
}
}
});
When I navigate back to the activity with the list view, I call a function getSelectedTrackers which I want to select the saved checkboxes based on the key in selectedTrackers
public static void getSelectedTrackers()
{
if (basicSettings.selectedTrackers.size() == 0) return;
for (int i = 0; i < trackers.size(); i++)
{
HashMap s = trackers.get(i);
String mob = (String)s.get("mobile");
for (int j = 0; j < basicSettings.selectedTrackers.size(); j++)
{
if (basicSettings.selectedTrackers.get(j).equals(mob))
{
View v = getViewByPosition(i, lv);
CheckedTextView ctv = (CheckedTextView) v.findViewById(R.id.trackerID);
ctv.setChecked(true);
//******************************
//some call to update the view HERE
//******************************
break;
}
}
}
}
Question: I have confirmed that the function finds the correct checkbox, but none of the check boxes are displayed as being selected after calling setChecked(). I have scoured SO and tried invalidating, refreshing drawable state, notifyDataSetChanged, and I can't seem to figure it out how to get it to work. What's the best way to do this? Any help is appreciated!
I am trying to find out the total number of selected rows in a customized list-view. If the number of items (rows) more than 2 then we cannot click the list-view again.Here I am using customized checklist(Multiple Choice)
What's wrong with listView.getCheckedItemCount()?
lvMain.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id)
{
int len = lvMain.getCount();
SparseBooleanArray checked = lvMain.getCheckedItemPositions();
for (int i = 1; i < len; i++){
if (checked.get(i)) {
count++;
/* do whatever you want with the checked item */
}
}
if(count>2)
{
/* do whatever you want with the checked item count more than one x value*/
lvMain.setSelected(false);
count=1;
}
}
});
Else, you could try to store your checkboxes and the other element displayed in a row (I've used TextView in my example) in a HashMap when overridden getView method get called and then count how many elements are checked iterating over the Map :
Iterator<Entry<TextView, CheckBox>> it = listCheck.entrySet().iterator();
int i = 0;
while (it.hasNext()) {
Entry<TextView, CheckBox> entry = it.next();
if (entry.getValue().isChecked())
i++;
}
return i;
I think you are trying to count the total number of selected rows in multiple listView.
for(i=0; listCount; i++) {
if(mListView.isItemChecked(i)){
}
else {
}
}
I have a ListView which is :
<ListView
android:id="#+id/list"
android:layout_width="290dp"
android:layout_height="166dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp"
android:visibility="gone"
android:choiceMode="singleChoice" />
And there is ImageView
<ImageView
android:id="#+id/cont"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:layout_marginTop="30dp"
android:src="#drawable/img" />
How I am adding data in my listview.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1, list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
I am trying to update the listview value :
View v=listView.getChildAt(position);
TextView tv= (TextView) v.findViewById(android.R.id.text1);
tv.setText(firstNameDialog.getText().toString().trim().toString()+" "+lastNameDialog.getText().toString().trim().toString());
But this is not changing the value
I want that when the image view is clicked then I can get the values of the listview item to get stored in the form of array. How could i get all the items values of a listview and how could set the values again on the clicked item
imageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int count = listView.getAdapter().getCount();
String[] listData = new String[count];
for (int i = 0; i < count; i++) {
listData[i] = listView.getAdapter().getItem(i).toString();
}
}
});
The process is quite simple, what you can do is, on clicking the image view, iterate through the array adapter which you are using to populate the listview. while iterating you can declare an array and keep inserting the iterated values inside it. Hope it helps!
Use the adapter. In cycle get the values from adapter :
StringBuilder b = new StringBuilder();
for(int i=0;i>adapter.getCount();i++)
b.append(adapter.getItem(i));//May be toString() should be used.
int wantedPosition = position; // Whatever position you're looking for
int firstPosition = mList.getFirstVisiblePosition() -mList.getHeaderViewsCount();
int wantedChild = wantedPosition - firstPosition;
if (wantedChild < 0 || wantedChild >= mList.getChildCount()) {
return;
}
Button btnEdit = (Button)wantedView.findViewById(R.id.btnEdit);
btnEdit.setText("my new message");
Have you tried something like this
for changing values of a list item you should do it in the adapter class.
so if your item has a TextViewyou should write a method in adapter like this
public void changeText(String newValue) {
this.myTextView.setText(newValue);
}
this is also the case when using view holder.
for getting all the items values, basically you should do what first answer said.
imageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int count = listView.getAdapter().getCount();
String[] listData = new String[count];
for (int i = 0; i < count; i++) {
listData[i] = listView.getAdapter().getItem(i).toString();
}
}
});
but except getCount you could use size().
but at least for me these relations between adapter and list is a little confusing.
hope it helps.
I'm trying to set a custom font on a list activity in Android. I can successfully do it once an item gets clicked, like so:
#Override
protected void onListItemClick(ListView listView, View listItemView,
int position, long id) {
int childCount = listView.getChildCount();
for (int i = 0; i < childCount; i++) {
TextView c = (TextView) listView.getChildAt(i);
c.setTypeface(mTypeFace);
}
However, before the item is clicked, assigning a font has no impact:
//
// Create the adapter to display the choice list
//
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.simple_list_item_single_choice_custom,
mAppState.mAnswerArray) {
};
/* attach the adapter to the ListView */
setListAdapter(adapter);
ListView v = getListView();
int childCount = v.getChildCount();
for (int i = 0; i < childCount; i++) {
TextView c = (TextView) v.getChildAt(i);
c.setTypeface(mTypeFace);
}
Debugging show that in the initial setup, the ListView v has zero children, despite the fact they show up in the GUI and mAnswerArray has the children.
Any idea what the problem might be?
Set the viewBinder and override the setViewValue in your adapter, like so:
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if(columnIndex == 7){
TextView textView = (TextView) view;
textView.setTypeface(gotham_book);
}
}
}
I have a collection of items in an ArrayList. I add them to a customer adapter as follows:
this.m_adapter = new MyAdapter(this, R.layout.myitem,
itemCart.m_items);
I have a delete button for each of these items in my list, but I am not sure how to connect the delete button's onClick() with the original item in the ArrayList. Can someone please explain how to do this or point me to a tutorial where I can read up on this? Non-sarcastic/non-condescending responses are greatly appreciated.
You can call the remove() method on your ArrayList
itemCart.m_items.remove(<index of element to remove>);
this.m_adapter.notifyDataSetChanged();
And then you need to call notifyDataSetChanged(); on your adapter to update the ListView
You can get the index of the element by simply noticed that a list view is a collection of child views (the rows of the list).
You can do something like this in your code:
(inside the getView() method, for example)
row.setOnLongClickListener(new OnLongClickListener()
{
#Override
public boolean onLongClick(View view) {
remove(listView.indexOfChild(view));
return true;
}
}
That is, the solution is simply use indexOfChild(View) method to get index of child view that user (long) pressed.
Here's my solution so far:
In the getView() method I do something like this:
deleteButton.setTag(position);
It looks like getTag() returns an Object. So I converted the position int into an Integer object first. It appears to be working.
In the OnClickListener() I do the following:
items.remove(index.intValue());
So far, so good.
Following works for me:
/* Read values from resource into an array */
String[] strColorValues = getResources().getStringArray(R.array.colors);
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < strColorValues.length; i++) {
list.add(strColorValues[i]);
}
ArrayAdapter adapterColors = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_item, list);
adapterColors.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerColors.setAdapter(adapterPermissionLevels);
spinnerColors.setOnItemSelectedListener(this);
/* Remove first element from the adapter and notify dataset changed. */
String item = spinnerColors.getItemAtPosition(0).toString();
adapterColors.remove(item);
adapterColors.notifyDataSetChanged();
Here's my Code.
transfer.setItemPosition(position, items.get(position).getAddMode());
the transfer here is the instance of the main class. everytime i click the deletebutton, it then pass the position of the that item on the list in this line.
public View getView(final int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
final Context context = getContext();
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.listviewitem_layout, null);
}
ItemEntry item = items.get(position);
if (item != null) {
TextView textViewName = (TextView) v.findViewById(R.id.textViewItemName);
ImageView imageViewDelete = (ImageView) v.findViewById(R.id.imageViewDeleteIcon);
imageViewDelete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
transfer.showDialog(4);
transfer.setItemPosition(position, items.get(position).getAddMode());
}
});
if (textViewName != null) {
textViewName.setText(item.getItemName());
}
if(imageViewDelete != null) {
imageViewDelete.setImageResource(R.drawable.delete);
}
}
return v;
}
}
Remove by position:
mainAdapter.remove(mainAdapter.getItem(position));
Such as the last one:
mainAdapter.remove(mainAdapter.getItem(mainAdapter.getCount() - 1));
Try these codes of lines it was very helpful for me
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
list.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, list.size());
}
});
If you use context menu, then you can get
AdapterContextMenuInfo and this structure gives index and id of clicked element.
It seems that you can get the index (or position) of a clicked item in the ListView as follows:
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
listview.remove(listview.getItem(position).toString());
}
}
So you need to listen for clicks on Views and then take the index from that.