Unable to get the position in a RecyclerView - android

I am trying to create a dynamic survey app, using a RecyclerView. I have no problem on initializing the primary questions. The issue is when I try to insert a row in the recyclerView.It is not placed where it is expected to be. I wanted the row to be inserted next to the current row. I tried several methods like getAdapterPosition, getLayoutPosition for viewholder but I cant get the selected correct position of the view. Furthermore, the RecyclerView does stores the old location of a view when something is inserted. Could someone help me to figure this out or is there any easier approach. Furthermore, Thank you guys, I'm a newbie programmer.. Here is a snippet of my Adapter where I create and initialize dynamic views.

What i always do and works fine is to use tag.
for example you have a radio button and you have an item ( Question , single choice etc... ) .
before you assign a clicklistener to your view just put that item as tag
MYVIEW.setTag(MyItem);
so in your clicklistener just do this :
new View.OnClickListener() {
#Override
public void onClick(View v) {
ITEM item = (ITEM)v.getTag();
int alwaysTruePosition = items.indexOf(item);
...
}
}
Important note is that you should define equal method in your ITEM class and there should be a unique identifier which helps you to define are two objects the same or not. (for example a unique id or unique name )

Related

How to programmatically change one RecyclerView item style?

I've got this RecyclerView, it's showing a list of persons with their names, phones and birthday.
I want to change the color of the item if the person's birthday is today, but I want to know if I should do the verification and change on my RecyclerView's adapter inside the OnBindViewHolder method, or if I should do it inside my activity calling my LinearLayoutManager or calling the item using the RecyclerView.getChildAt() method.
Should I go whit the first option, using the onBindViewHolder?
YES . Should you choose to make changes in the onBindViewHolder().
We'll take a sample:
#Override
public void onBindViewHolder(FeedsViewHolder feedViewHolder, int i)
{
if(d1.feeds.get(i).getFeedContentType().equals("b-day")) // <-- Pointing to the List that contains value, and checks if it equals to a sample string
{
feedViewHolder.n1.setText("Birthday"); // <-- if it equals, party time :D , and sets text to the corresponding TextView in the RecyclerView
}
}
Hope it helps :)

OnItemClickListener use for TableRow

I want to know which column user pressed in one TableRow object. It is header of table and i want to set sorting of items by chosen column.
I am able to use onClick listener in this case.
Problem is simmilar to How to click an specific TableRow within a TableLayout
You can do it like:
set Tag to each tablerow as follow:
tablerow.setTag(pass object of item which you want to set on this tablerow)
Now, set Listener:
tablerow.setListener(listener);
Listener should be pass from fragment/activity to Adapter.
So, when you click on any row, you will be able to listen it in fragment as:
listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
v.getTag(); here you will get object which you set above.
}
}
So, using the tag object, you can able to find which row it is.
i would suggest using different layout for showing the data. GridView would be a nice solution. GridView docs There you should have the correct event, you are looking for On item click listener

How to change number of column of a gridview at same visible item. Android

I am writing an android app where I am using a grid view to display some items. I want to give users a configurable view where they can change the no of columns on the activity by clicking floating action button. I am changing the column no using
gridView.setNumColumns(selectedColumnNo);
This is working fine But the problem is if a user changes no of column after some scrolling the First Visible Position is set to the first item of the array list, so the user has to scroll the view again. Can someone please tell me where I am doing wrong. Or Is this the proper way to do this or should I use a different approach.
A code snippets will be helpful
Thanks.
Update::
currently I am using the bellow snippets
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int firstPosition = gv.getFirstVisiblePosition();
if(gv.getNumColumns()==2)
{
gv.setNumColumns(1);
gv.setSelection(firstPosition);
}
else {
gv.setNumColumns(2);
gv.setSelection(firstPosition);
}
}
});
Now the problem is on every 4th switch grid view is showing the first element of the arraylist
Right before you call setNumColumns(), save the GridView's first visible position:
int firstPosition = gridView.getFirstVisiblePosition();
Then, after you change the number of columns, pass that integer to setSelection():
gridView.setSelection(firstPosition);
"Selection", counter-intuitively, is not the same thing as "activation". It will ensure that the view is on-screen, but not visibly affect it in any other way.

Expandable Listview Child count Dynamically

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.

Setting tags to each item in a ListView in Android?

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.

Categories

Resources