Within RecyclerView, any tips on loading a different viewholder onitemclick? i'm having trouble wrapping my head around loading viewholder 2 when item is clicked in viewholder 1 at that position. both viewholder 1 and 2 are a list of cards. so say for example. vh1 contains a sample hotel image. When you click that vh2 shows you contact details of that hotel - at that position, while retaining vh1 through out the other un-clicked contents.
I did ask a question like this before and i think it was a bit vague so people suggested i change information based onitem click. The problem is vh1 and 2 are different layouts completely so this wouldn't work for what i'm working on.
is this even possible?
Thanks
You can create another adapter for your RecyclerView. Create a new Java class, call it whatever you want. In your main activity, or the activity where you're setting your adapter, you can create a function like this:
public void setNewAdapter() {
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.your_recyclerview_id);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
NewAdapter adapter = new NewAdapter(// any arguments);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
In your adapter, you can create a new instance of your activity. For example, if you're activity is called MainActivity, you can add this code in your onItemClick:
MainActivity mainActivity = new MainActivity();
mainActivity.setNewAdapter();
See if that works.
I'm adding list items containing a checkbox to a list in my fragment class like this:
public class CheckboxList extends Fragment {
...
listViewToDo = (ListView)myView.findViewById(R.id.listViewToDo);
//creates list of names of the default list items
arrayListToDo = new ArrayList<String>();
if(!arrayListToDo.contains("Menu1"))arrayListToDo.add("Menu1");
if(!arrayListToDo.contains("Menu2"))arrayListToDo.add("Menu2");
if(!arrayListToDo.contains("Menu3"))arrayListToDo.add("Menu3");
//sets the checkboxes
arrayListCheck = new ArrayList<>();
for(int i = 0; i < arrayListToDo.size(); i++){
CheckBox cb = new CheckBox(myView.getContext());
cb.setText(arrayListToDo.get(i));
arrayListCheck.add(cb);
}
arrayAdapterCheck = new ArrayAdapter<CheckBox>(listViewToDo.getContext(),
android.R.layout.simple_list_item_checked, arrayListCheck);
listViewToDo.setAdapter(arrayAdapterCheck);
...
I want it to do it this way because the user shall be able to add and delete specific list items.
Though that works fine, my checkboxes look like this:
Can someone tell me what I'm doing wrong?
Ok my fault, I did'nt know that I need a custom ArrayAdapter to use other objects then strings to display in my list.
This helped me a lot to get a better understanding of the Adapter and to write my own one for the checkboxes:
http://techlovejump.com/android-listview-with-checkbox/
EDIT: Thanks to #ankit aggarwal, I got one part working, which is TAB 1 not switching to TAB 2. Still need assistance on the view not refreshing in TAB 2.
I am working on an app, in which I am using tabs. I based my app on an example I found on the internet here.
What I have is a ListView in TAB 1. What I want to happen is when I click on an item in the list, it will send an ID to TAB 2, where I want to populate another ListView based on that passed data. I am having issues getting this to work properly.
Currently, I have it working so that if I click an item in the list on TAB 1, then TAB 2 does get the data and populates the new list, however it adds to the view on TAB 2 instead of refreshing/overwriting/etc., and the app does not automatically switch to the new tab. This is what I have for the layout in TAB 2 (i.e., the receiving tab):
person.xml
<LinearLayout android:id="#+id/person_information_layout">
<TextView android:id="#+id/header_row" />
<LinearLayout>
<TextView android:id="#+id/column1_row_header" />
<TextView android:id="#+id/column2_row_header" />
<TextView android:id="#+id/column3_row_header" />
</LinearLayout>
<ListView android:id="#+row_of_data"></ListView>
</LinearLayout>
I am populating this list in the receiving tab (TAB 2) with an AdapterView and a database Cursor.
PersonInformation.java
package myPackage;
public class PersonInformation extends Fragment {
private View rootView;
private DatabaseHelper myDBHelper;
private Cursor informationCursor;
private SimpleCursorAdapter mySimpleCursorAdapter;
private TextView personIDDisplay;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.person, container, false);
personID = getArguments().getString("personID");
myDBHelper = new DatabaseHelper(getActivity());
informationCursor = myDBHelper.getInformationCursor(personID);
String[] fromColumns = {"firstname", "lastname", "homephone", "homeaddress"};
int[] toViews = {R.id.firstname_textview, R.id.lastname_textview, R.id.homephone_textview, R.id.homeaddress_textview};
mySimpleCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.person_information, informationCursor, fromColumns, toViews, 0);
personIDDisplay = (TextView) rootView.findViewById(R.id.header_row);
personIDDisplay.setText("Person ID: " + personID);
ListView myListView = (ListView) rootView.findViewById(R.id.row_of_data);
myListView.setAdapter(mySimpleCursorAdapter);
myDBHelper.close();
return rootView;
}
}
This is the person_information layout that gets populated:
person_information.xml
<LinearLayout>
<TextView android:id="#+id/column1_data" />
<TextView android:id="#+id/column2_data" />
<TextView android:id="#+id/column3_data" />
</LinearLayout>
And here is my sending tab (TAB 1)
Home.java
package myPackage;
public class Home extends Fragment {
private View rootView;
private DatabaseHelper myDBHelper;
private Cursor personCursor;
private SimpleCursorAdapter mySimpleCursorAdapter;
private Activity myActivity;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
rootView = inflater.inflate(R.layout.home, container, false);
myDBHelper = new DatabaseHelper(getActivity());
personCursor = myDBHelper.getPersonCursor();
String[] fromColumns = {"personID"};
int[] toViews = {R.id.person_id_textview};
mySimpleCursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.person_layout, personCursor, fromColumns, toViews, 0);
ListView myListView = (ListView) rootView.findViewById(R.id.person_row);
myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor subCursor = (Cursor) mySimpleCursorAdapter.getItem(position);
String personIDNumber = subCursor.getString(subCursor.getColumnIndex("personID"));
PersonInformation personInformation = new PersonInformation();
Bundle myBundle = new Bundle();
myBundle.putString("personID", personIDNumber);
personInformation.setArguments(myBundle);
getFragmentManager().beginTransaction().replace(R.id.person_information_layout, personInformation).commit();
}
});
myListView.setAdapter(mySimpleCursorAdapter);
myDBHelper.close();
return rootView;
}
}
As you can see, I have a layout with a top information row, then a row of column headers, then the rows of data. What I want is this:
Top Information Row
Column Headers
data row 1
data row 2
...
data row n
Currently, when I click the person in TAB 1, TAB 2 does get the data from TAB 1 and populates a new list correctly, however it draws it under the already existing top information row and column headers, so I have layers:
Top Information Row
Column Headers
Top Information Row
Column Headers
data row 1
data row 2
...
data row n
Also, the tab does not automatically switch from TAB 1 to TAB 2 when I click a row in TAB 1.
Instead of this line in the sending tab (TAB 1)
getFragmentManager().beginTransaction().add(R.id.person_information_layout, personInformation).commit();
I changed it to this line:
getFragmentManager().beginTransaction().add(R.id.row_of_data, personInformation).commit();
But I got the error:
"addView(View) not supported in AdapterView"
From what I understand, I cannot addView to a ListView, so I changed it back to the parent of the ListView, but then I get the duplicate view.
I keep coming back to wanting to change the line in my receiving tab (TAB 2) from
ListView myListView = (ListView) rootView.findViewById(R.id.row_of_data);
to this
LinearLayout myLinearLayout = (LinearLayout) rootView.findViewById(R.id.person_information_layout);
But the cursor adapter will not work with that.
What do I need to do to get this working?
(1)
Currently, when I click the person in TAB 1, TAB 2 does get the data
from TAB 1 and populates a new list correctly, however it draws it
under the already existing top information row and column headers, so
I have layers:
It is happening because this statement instead of switching to tab2, it is adding a new fragment on top of your activity's frame.
getFragmentManager().beginTransaction().add(R.id.person_information_layout, personInformation).commit();
(2)
Also, the tab does not automatically switch from TAB 1 to TAB 2 when I
click a row in TAB 1.
You are using a viewpager in this tabs implementation. So to change to tab2 you can do
viewPager.setCurrentItem(2);
NOTE: What you are missing here is a view pager automatically loads a page previous and the next one to a particular page. So when you are in tab1, tab2 would have already been loaded. So your tab2 won't refresh when you click on list item because it would have already loaded.
The way I solved a similar problem is by creating a callback method from the activity to the fragments and a callback method from the fragments to the activity. When I click on a row in the list of fragment1, I save the information in the arguments of that fragment, and call the callback function of the activity. In that function, I retrieve the information passed and load it to the arguments of fragment2 and call the callback function of fragment2. There I retrieve the information passed and update the list of fragment2. I then call tabLayout.getTabAt(newPosition), in the activity, to redisplay the page of fragment2. You also have to make sure that since the views of the fragments are destroyed as one move between pages, to check in the fragment that the list is still populated and if not to restore the items of the list.
I'm trying to add a custom view to my listview (which is already populated) using this code:
listview.addView(customView,rowNumber);
but my app crashes..
I realized that if I use this code :
list.addFooterView(customView);
it works, but I can't choose where to place the view . What can I do?
The addFooterView works because it adds on the bottom. You can't add anything in the Listview just putting it using addView. Instead, do the following example:
After doing it:
ArrayList<Object> _views = new ArrayList<Object>();
_views.add(new View());
_views.add(new View2());
ArrayAdapter<Object> _adapter = new ArrayAdapter<Object>(getActivity(), android.R.layout.simple_list_item_1, _views)
mListView.setAdapter(_adapter);
You only need to add the new View into ArrayList and notify the adapter that the listview had changed such as:
_views.add(new View3());
_adapter.notifyDataSetChanged();
I have a very simple ToDo list app with multiple categories the user can add an item to. The architecture looks something like this:
http://i.imgur.com/WA3dtcU.png
I am using a ViewPager and each view is a fragment that I instantiate in the ViewPagerAdapater:
public Fragment getItem(int i) {
ToDoCategoryModel cat = categories().get(i);
ToDoCategoryView view = ToDoCategoryView.newInstance(cat);
return view;
}
Within each of these category the user can add new Item Fragments to a Linear Layout.
A very strange thing happens though. I start off on Category 1 (C1) Which currently has 1 Item in the list. Then scroll to C2 then scroll again to C3. Then I scroll back to C2. The ViewPager asks my ViewPagerAdapter to re-create C1 as it was destroyed after having scrolled 2 pages away from it. This is fine, I just create a brand new fragment (as the code above shows). However, when I now scroll back to C1, instead of 1 Item being shown (as you would expect) there are 2 items shown. They are a duplicate of each other.
The code I use to add the Item fragment to the Category fragment is:
public void addToDoItem(ToDoItemModel model) {
ToDoItemView newItem = ToDoItemView.newInstance(model, this);
getChildFragmentManager().beginTransaction().add(_linearLayout_items.getId(), newItem, "sameTag"+count++).commit();
}
If I change this code to add new TextView instead of fragments:
public void addToDoItem(ToDoItemModel model) {
ToDoItemView newItem = ToDoItemView.newInstance(model, this);
TextView tv = new TextView(getActivity());
tv.setText(newItem.getModel().getName());
_linearLayout_items.addView(tv);
}
It works fine! There are no duplicate items shown.
So what is wrong with adding fragments dynamically using the child fragment manager within a view pager?
Thanks.