Add new layout to an existing item in RecyclerView - android

I would like to add a new container layout to an existing XML item of a RecyclerView
Here is an example of what I would like to do (based on R.layout.item_simple XML)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(inflater.inflate(R.layout.item_simple, parent, false));
}
R.layout.item_simple content at RecyclerView.Adapter creation:
______ LINEAR LAYOUT
______ IMAGE VIEW
______ TEXT VIEW
What I want to do by adding a new layout to the user view:
______ RELATIVE LAYOUT
______ LINEAR LAYOUT
______ IMAGE VIEW
______ TEXT VIEW
Is it possible to change this item view, preferably into the RecyclerView.Adapter ?

There are two ways to achieve this. First is to add always the additional layout to your item_simple and hide/show. The second approach is to use getItemViewType to return different layout types. This way onCreateViewHolder gets called once for each type, and you can inflate different layouts

You just simply inflate your layout here like item_simpleand use show/hide view by using condition. like
mainlayout.setVisibility(View.GONE);
and
mainlayout.setVisibility(View.VISIBLE);

Related

How to use recycler view and relative layout in a screen in android studio

I have a recycler view and a relative layout below recycler view. My relative layout consists of three text views.My recycler view consists of three text views and a button. My problem is recycler view is scrolling separately and textviews in relative layout are fixed. But I want both to be scrolled, which means while scrolling the screen scroll should be done for both recycler view and relative layout but not seperately. While scrolling my relative layout should be attached to the end of recycler view. I have searched a lot for doing that but there is no results for my search. So, ended up here please anybody help me out.
You have 2 options, first one (the better one) is to create a footer ViewHolder and add it to RecyclerView as a last item in adapter.
Or you can simply wrap your views in vertical LinearLayout and then wrap it in NestedScrollView like this:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
In order to get your RelativeLayout to scroll with the content of your RecyclerView, you'd need to add the RelativeLayout with static content to the end of the list your Adapter iterates. You'd then override getItemViewType in the adapter and return one type ID for the data in your RecyclerView and another for the footer RelativeLayout. Then in onCreateViewHolder you'd use the view type to inflate the right kind of view (one that binds your data or another that displays your RelativeLayout).
This process can be pretty labor intensive. You might also consider using a library like Epoxy to help create a footer view in your RecyclerView.
You can add view with text views in different layout and add to your recycler as last element. Then check posotion in getItemViewType and if it last return footer type inside RecyclerAdapter.
private static final int FOOTER = 1;
private static final int CHILD = 2;
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == CHILD){
View view = mInflater.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
else if(viewType == FOOTER ){
View view = mInflater.inflate(R.layout.relative, parent, false);
return new ViewHolder(view);
}
return null;
}
#Override
public int getItemViewType(int position) {
if (position == getItemCount() - 1) {
return FOOTER;
} else {
return CHILD;
}
}

How to Construct a RecyclerView with Children of Variable Height?

The app I am working on contains lots of listviews. In one case, I have a recyclerView that leverages the GridLayoutManager to create a two column view. I haven't worked with recyclerViews yet as far as adapters go but here is the problem I am having. Each item in the view is being sized to the same height despite having the appropriate wrap_content attributes. I guess my question would be, is there a trick to pull this off where each child element has a different height? Is something going on behind the scenes with a recyclerView that causes all children to have a fixed height of the tallest child element? Does this sound like a recycler problem with the view holders?
My adapter logic is as follows
public ClubViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.onboard_club, parent, false);
return new ClubViewHolder(itemView, mRecyclerClickListener);
}
public void onBindViewHolder(final ClubViewHolder holder, int position) {
Item club = clubList.get(position);
if (null != club) {
holder.clubTitleText.setText(club.getName());
holder.subtitleText.setText(context.getResources().getString(R.string.club_members,club.getNumberMembers()+""));
// Do some imageView logic here
}
}
Do I need to set height in here programmatically?
EDIT: To clarify further, the layout I inflate is the layout in question here. It is a Vertical LinearLayout containing an imageView, and two text views. I need the LinearLayout to wrap the children XML attributes but it currently isn't doing that despite the LL having a height of wrap_content and all children height set to wrap_content as well
SOLUTION: Solution was posted by a user below. I will leave the update here for anyone struggling in the future.
Layout I need: Two columns whose children vary in height
Tie it in with an adapter as you normally would.
Set a StaggeredGridLayoutManager on the recyclerView widget
In the manager constructor pass in a spanCount of 2 and an Orientation of Vertical
Boom, close the sprint ticket and forget about it
Thanks again Stack Community, cheers!
The best way to control placement and size of item for RecyclerView is through its LayoutManager.
If you're looking for GridView with elements that resize themselves according to the content you can use StaggeredGridLayoutManager
Nice example of Staggered Grid Layout can be found here.
On the other hand if you need just few "groups" of different Items you can inflate different ViewHolders depending on some criteria. Here is the sample code for two types of views.
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == FILE_FLAG) {
ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
.inflate(R.layout.file_item, parent, false);
return new FileViewH(view);
} else if (viewType == DIR_FLAG) {
ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
.inflate(R.layout.dir_item, parent, false);
return new DirViewH(view);
}
}

Add a header/footer in a listview in xml

I know how to add a header or a footer in JAVA, but I was wondering if I could add it straight in the XML.
I wouldn't want to simulate this, but really add it as footer or header!
No, I don't think that it is possible. Based on ListView source code there are only overScrollHeader/overScrollFooter are available from XML attributes. But these attributes accept only drawables.
If you don't want to use tricks with layouts above/below ListView. You can extend ListView and implement your own footer and header support in customized View. It is not so hard because of footer and header are already implemented. You only have to add XML attributes parsing in your customized View's constructor.
I was just trying to achieve the same thing (to keep my code cleaner and use XML for markup & source code for logic), but the only solution I found is to define the header view with XML somewhere in your layout and then detach it and put into ListView as header.
For example, having this XML:
<ListView android:id="#+id/myListView">
</ListView>
<LinearLayout android:id="#+id/myHeader">
....
</LinearLayout>
You can do this in your code:
ListView myListView = (ListView) findViewById(R.id.myListView);
LinearLayout myHeader = (LinearLayout) findViewById(R.id.myHeader);
// Let's remove the myHeader view from it's current child...
((ViewGroup) myHeader.getParent()).removeView(myHeader);
// ... and put it inside ListView.
myListView.addFooterView(myHeader);
Basically, what we do here is just detach the inflated LinearLayout from its parent and set it as ListView header child.
This is not an ideal solution, but it is still easier than creating/inflating header manually. Also this utilizes the power of XML inflation & view reusing if you're using this inside some "holder" pattern.
Hope this helps somebody.
This is how it worked for me, in my Adapter class which extends the BaseAdapter. I am targeting API 23:
#Override
public View getView(int position, View view, ViewGroup parent) {
if (position == 0) {
if (view == null) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
view = layoutInflater.inflate(R.layout.test_results_header, parent, false);
}
} else {
if (view == null) {
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
view = layoutInflater.inflate(R.layout.test_result_item, parent, false);
}
}
Pretty simple, I inflate a header XML for position 0 and the content XML for the rest. If you know the position where you want a header or any other XML, in your logic you would need to check the position, and inflate the respective XML for that position.
I created an xml resource same as my adapter rows xml (so the title is fit) and added it to the listview after addind the adapter:
listView.setAdapter(myRowsAdapter);
listView.addHeaderView(View.inflate(getContext(), R.layout.title_row, null));

How to do my own custom list?

How to do my own custom list? I mean, that each element of list will be looking like I want.
Create a custom list item row layout
You have to create a custom list row item in the layout folder, just like you define the usual activity layouts. There you place your icons, TextViews etc and place them properly.
Override the specific adapter you need
You then need to override the specific adapter you need in order to associate the data from your curso / object list with your layout xml element. This is usually done by overriding the getViewor bindView method of the adapter of your choice (ResourceCursorAdapter, ArrayAdapter,..).
#Override
public View getView(int position, View convertView, ViewGroup parent){
if(convertView == null){
convertView = mInflater.inflate(R.layout.row_item, parent, false);
}
TextView someTextViewOnMyRowLayout = (TextView)findViewById(...);
someTextViewOnMyRowLayout.setText(...);
return convertView;
}
You can create an xml file which acts as an element that looks like you want..
and assign that to the list using inflators and adapters..
Try this..
http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/ ,
http://www.androidpeople.com/android-custom-listview-tutorial-example/

can we bind 3 controls into a single control in android?

I have 2 textviews and one imageview and i want to bind them into a single control so that i can implement horizontalScrollView on them...
Is there a way to merge different controls so that we can use them???
Or is there a way to implement horizontalScrollView on multiple controls simulataneously??
Thanks in advance
You can build an xml layout that you inflate into a GaleryView. Android allows you to build any mashup of controls into a layout and then use that layout for each row in a listview or each item in a sliding galery.
in a ListAdapter you can inflate the layout and set all of the properties.
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater factory = LayoutInflater.from(context);
View row = factory.inflate(R.layout.list_row, null);
TextView main = (TextView)row.findViewById(R.id.labelMain);
TextView details = (TextView)row.findViewById(R.id.labelDetails);
ImageView icon = (ImageView)row.findViewById(R.id.imgIcon);
main.setText(_items.get(position).Title);
details.setText(_items.get(position).Description);
icon.setImageResource(R.drawable.pin);
return row;
}

Categories

Resources