I want to create a custom ListView.
Initially, the custom ListView has one array of data, but when user taps one of the list items, it's then removed from current array and added to another. If the user taps on the second array, the list item is then added back over into the first array.
Please suggest how to apply logic to do this.
Updates : I wants to use only one listview/recyclerview.
Following are screen shots..
Regarding the object switch - this is a simple transfer between lists, , just know beforehand if the insertion and removal is index based, e.g:
contacts.add(iLocation, ContactObject);
favorites.remove(iOtherLocation);
Regarding the ListView stuff, I would suggest converting to RecyclerView, let's build a general scenario:
You have a screen (Activity or Fragment) that holds one list (the implementation can be ListView or Recycler), and another screen that holds the other list.
In both of your lists you have adapters in which you implement the logic for the clicks on the objects in the lists.
The click transfers the object, either directly to the other list, OR to a temporary Object holder (because you might need it for other stuff), in which case you will need to pull that object from the other view, either way you remove it from the current one.
you switch to the other view, and refresh it.
An easy way to go -
Assuming the screens are the same, use only one Activity, holding a single RecyclerView, and handle 2 adapters, each for every list, the adapters allow you to handle the clicks easily, with an index for the object clicked, the click executes the info swap action,the Activity handles the visual swap Action.
a very general example would be:
//init everything obviously ;)
List<ContactObject> contacts;
List<ContactObject> favoritesContacts;
//the AdapteListener is an interface declared inside the adapter
mContactsRecyclerAdapter = new ContactsRecyclerAdapter(this, contacts,new ContactsRecyclerAdapter.AdapterListener()
{
#Override
public void cellClicked(int iIndex, ContactObject object)
{
favoritesContacts.add(iIndex, ContactObject);
contacts.remove(iIndex);
mContactsRecyclerAdapter.notifyDataSetChanged();
mFavoritesRecyclerAdapter.notifyDataSetChanged();
mRecyclerView.swapAdapter(mFavoritesRecyclerAdapter, false);
}
});
And vice-versa for the other adapter.
Hope this helps, comment if you have problems and I'll update.
Please implements with custom view extend with Linearlayout
Custom view has 2 child Linearlayout in which will add with this custom view
First time add all the element in first Linearlayout and based on user action please remove from first Linearlayout and add it in another layout
Related
I am doing a side project of making an app (with Java since I already know it). I have a recyclerview which loads some data via the room database library. The elements of the recyclerview are clickable.
My problem is I want the user to be able to sort the recyclerview so that the most recently accessed items go to the top.
My original idea was to assign the entities to have two variables - a String list_name which also serves as the id, and an Int order_of_access. Also, in my ViewModel I have a getAllLists method which returns a livedata list. I have an onChanged listener in the fragment activity which nicely updates the recyclerview when data is added/removed.
When the user adds a new list, it is assigned an order_of_access of the listsize (+1). But when the user deletes a group of lists, or clicks on a list, I want to update the order_of_access, say with an updateOrderAccess method.
Do you think this is the best way of doing what I want?
Where should I place updateOrderAccess and how would you recommend it be written? Since the method getAllLists returns livedata, it is tempting to put updateOrderAccess in an observer in the fragment (in onChanged) - but this will obviously create an infinite loop. It seems more in the correct philosophy to put it in the ViewModel, but then how would you suggest the updateOrderAccess method to be written? I'm having some trouble conceptualising what I need.
I hope the question is not too vague - I will update it if you need more details.
Where should I place updateOrderAccess and how would you recommend it
be written?
I am so sure that you must write it in the view model, as long as updateOrderAccess() is editing the list which is observable then you have andexpose by that the ui state then you have to put it in view model, and the observers will be notified ( in this case it is recycle view) and it will redraw the list in the order you offered.
note: do not you ever update the state(ui data) outside the state holder so you implement UDF (unidirectional Data Flow) pattern.
see the references below to read more about UDF so you never get confused where to declare your functions by letting the architicture lead you:
Guide to app architecture
ui layer
state holders and ui state
Do you think this is the best way of doing what I want?
i am not very sure that i got exactly what your app do, but it seems like you want to re-order the elements of recycle view depending on the ui event (click) or data change (deleting or adding new element), now you have two choices:
if the order is very importnat to you that much you want to keep it even if the app has been destroyed
then you have to add a field in the room entity represent the ordering (let us call it order) and whenever the user click on the recycle view you have to update the rooms field "order" which is "flow" or "liveData" or any observable type, that will tell the view model that there is a changing in the data, now the view model have to re-order the new data by the field "order" and pass it to the recycle view to show it.
if your app do not have to save the order changes after the app been destroyed
then you can simply do that:
create list which is called "orderedList" you will put the list items in it by the right order, and another list called "unorderlist" which have getAllLists
for the first case where the ordering is being changed by user click, you
can declare a function in viewModel then use it in the ui
controller (your activity or fragment), so whenever the list item is
clicked this function just re-order the orderedList elements ( which
is observable, so the changes reflect on the ui ) just by change the
clicked item position to the front of the list.
for the second case where the ordering changes by data changes like
add or delet a list item in the database, then you have to compare
the legnth of orderlist and unorderlist legnth, if unorderList is
longer then it is an add situation else it is a delete situation, in
adding case just add the last item of unorderList to the orderList,
else you have to check the deleted item and delete it from
orderList.
The problems is: I have a listview_products, for instance, and I have to select one of them per time and put it into another listview_sales, the listview_sales is going to hold all the products that I've been choosing for then make the proccess of sale completely. How could I achieve this behavior? Could you lend me a hand with this please!
You should have an ArrayList with object from where your first adapter gets data to draw.
Then you will need another arrayList with the objects of the first that will be drawn on the second ListView.
So, if you implement a OnItemClickListener in your first arraylist to get the selected items.
This is just a pseudocode example.
void OnItemClicked(int position) //This is not the real method definition
{
secondArray.put(firstArray.get(position));
}
Then when you want to show that second List just pass that data to its adapter
secondListView.setAdapter(new SecondAdapter(secondArray));
Hope this helps.
I am making an web service based Android application. My problem is child count with expandableListView. I must use 2 different web services. Namely, 1st web service is getting parent informations. I want this, when i clicked parent 2nd web service must start and get child informations. My child counts are flexible. 1st parent have 2 childs, 2nd parent have 5 childs. How can i manage them.
I am using expandablelistviewadapter. This adapter want child counts before using this code "listview.setadapter(adapter)"
So I want to use dynamic child counts. When I clicked parent dialog will show and childs getting from server.
I don't get your questin. Writing a custom adapter is the way to go in most cases. So you are on the right way. This adapter should use a datastructure what does what you want.
edit:
this should work right? (Item is my baseclass for dynamic data)
public class MyBaseListAdapter implements ListAdapter {
List<? extends Item> items;
#Override
public int getCount() {
return items.size();
}
edit II:
this line may also be improtant for you:
adapter.notifyDataSetChanged();
and you should try to sync or block access while you change the data
you should give the child count as what u have for each parent i.e. 0. When parent is clicked, get the children for the clicked parent, update ur data-structure and then call adapter.notifyDataSetChanged();
So I want to use dynamic child counts. When I clicked parent dialog
will show and childs getting from server.
There's nothing dynamic about the child counts, you just need to update the adapter when the child data becomes available. As the other answers have pointed out, you need to implement a custom adapter. The basic flow would be:
make the first webservice call to retrieve the group data.
when that call finishes build an instance of your custom adapter where the child count(getChildrenCount()) is zero(because we don't have any data). Ideally you'll show the user some sort of indicator that data is being retrieved. You spoke about a dialog, I would go(and my example is based on this) with a custom child row which indicates loading(in which case you would return 1 from getChildrenCount()).
in the OnGroupClickListener make the call to the webservice to retrieve the data for that particular clicked group. You'll also need to make sure that only the first group click makes the request to fetch data.
when the child data for a group becomes available update the adapter(or make it fetch the new data) and call notifyDataSetChanged().
I've made a small sample on how you might approach this(to indicate that the data is being retrieved for a group I make that clicked group to show a loading child row while the data isn't yet available). The code is commented and you can find it here.
MvvmCross version 6.2
_myExpandList = view.FindViewById<ExpandableListView>(Resource.Id.yourExpandedList);
int ExpandViewCount = _myExpandList.Adapter.Count;
I was looking for this all day and grew increasingly annoyed by all the answers. This seems to be the simplest solution.
I have a ListView where I want each item to have an ID number attached to it (not the same as the position number). I was hoping this could be done by setting a tag to each View item in the ListView using setTag() when these Views are being created.
Right now I'm creating the ListView like this:
final ListView listview = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, names);
listview.setAdapter(adapter);
The names variable in the ArrayAdapter parameters above is an ArrayList, and each string value in this list also has a unique ID that I want to link to this string somehow.
Is there any way I can get access to and modify each of the Views with a tag? One idea was to create my own extended class of ArrayAdapter and override the getView() method, but I don't really understand how it works and how I would go about doing this.
Or is there a better way to link IDs with each string like this than adding tags like I'm trying to do?
Create a ViewBinder and set the tags as the ListView is being populated with whatever you need. You can check all properties of the view to determine what tag goes where, so this should be what you're looking for.
myAdapter.setViewBinder(new MyViewBinder());
public class MyViewBinder implements ViewBinder {
#Override
public boolean setViewValue(View view, Object data, String text){
//Since it iterates through all the views of the item, change accordingly
if(view instanceof TextView){
((TextView)view).setTag("whatever you want");
}
}
}
I just used this exact same answer on another question (albeit slightly different) yesterday.
about getView , it works by using a method of recycling views. i will try to explain it in a simple way.
suppose you have tons of items that can be viewed . you don't want to really create tons of views too , since that would take a lot of memory . google thought of it and provide you the means to update only the views that need to be shown at any specific time.
so , if there is an empty space on the listview , it will be filled with a new view . if the user scrolls , the view that becomes hidden is recycled and given back to you on the getView , to be updated with the data of the one that is shown instead .
for example , if you scroll down , the upper view becomes hidden for the end user , but in fact it becomes the exact same view that is on the bottom .
in order to understand how to make the listview have the best performance and see in practice how and why it works as i've talked about , watch this video:
http://www.youtube.com/watch?v=wDBM6wVEO70
as for tags , i think you want to do something else , since the data itself (usually some sort of collection, like an arrayList) already knows where to update , because you get the position via the getView . if you want a specific view to update , you might be able to do so by using a hashmap that keeps upadting , which its key is the position in the collection , and the value is the associated view . on each time you go to getView , you need to remove the entry that belong to the view (if exists) and assign the new position with the view that you got/created .
Thanks for the answers. thisMayhem's answer would probably have been easier in the end, but on my quest to learn more I ended up making my own adapter according to this tutorial. I pass down the names and the IDs into the adapter and set the names as the text of the TextViews and the IDs as the tags.
I would rather go with the solution discussed in this thread. It is always the easiest to have all related data in same place and in this case you just create a class to hold all the information you will need for every item.
I need help on a specific task :
I have a ListView in my main activity with a custom Adapter associated, and an OnItemLongClick listener that displays a Dialog with many operations configured (change quantity, cancel item...) and it works like a charm.
My goal is to have a physical copy of the clicked item in the Dialog, to display immediately the changes made.
Since my ListView item is complex and designed by the Adapter, i can't just get the reference to the original object, i need a visual copy of the selected ListView item...
I thought about creating the same structure (ListView and Adapter) with only the selected item associated but it's kind of heavy...
Is there a simpler solution that can help me in this situation ? I mean real copy of the original ListView Item with changes made in my Dialog done to the original object...
Posting your relavent code may help us to guide you more clearly.
However you can get your object in onItemLongClick((AdapterView, View, int position, long) using position params i.e
YourObject objReference = yourActivityClassObjectList.get(position);
now when showing dialog, pass this objReference to your dialog and when changes made, change the contents of this objReference and call
adapter.notifyDataSetChanged();
instead of passing the objReference to dialog, you can pass int position and while changes made, get the reference to that object, change contents and notify data set changed to Adapter.
When you click on one listview item the onListItemClick callback should be fired. As you see in the doc the third parameter is position. You can call YourAdapter.getItem(int) to retrive the element hold by the listview at position