Set Sticky Header and Items Layouts Recyclerview - android

I want to build a complex layout using recyclerview android. In the layout, I want to have a camera button to the top left fixed and a recyclerview wrapped around it with gallery images. I have checked flexbox layout manager for recyclerview but it doesn't seem to match my use-case.
I want the header to be non-repeating and not to scroll with other items vertically. Here's the layout for the header:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/shareLayout"
android:layout_width="185dp"
android:layout_height="135dp"
android:layout_below="#id/trendingToolbar"
android:background="#color/black">
<ImageView
android:id="#+id/cameraShareIV"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
app:srcCompat="#drawable/camera_white" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/cameraShareIV"
android:layout_centerHorizontal="true">
<TextView
android:id="#+id/infoTxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="20dp"
android:gravity="center_horizontal"
android:text="#string/share_pic_video"
android:textColor="#android:color/white"
android:textSize="13sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/infoTxt"
android:layout_marginLeft="16dp"
android:text="#string/share_timeout_txt"
android:textColor="#color/colorPrimaryDark"
android:textSize="11sp"
android:textStyle="bold" />
</RelativeLayout>
and in my activity, here's the XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="base.android.com.thumbsapp.UI.Fragments.TrendingFragment">
<include layout="#layout/trending_toolbar"
android:id="#+id/trendingToolbar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/trendingRV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/trendingToolbar"/>
Previously, I had the header inside the activity XML but had no way to wrap a recyclerview around it. So, I have decide to use an adapter like below:
public class TrendingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = TrendingAdapter.class.getSimpleName();
private Context context;
private List<Trending> itemList;
private static final int HEADER = 0;
private static final int ITEMS = 1;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
switch (viewType){
case HEADER:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_header, parent, false);
return new TrendingHeaderViewHolder(v);
case ITEMS:
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.trending_items_layout, parent, false);
return new TrendingItemsViewHolder(v);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Trending tr = itemList.get(position);
if (holder instanceof TrendingHeaderViewHolder){
((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
// TODO: 4/2/2018 select image from gallery
});
} else if (holder instanceof TrendingItemsViewHolder){
// TODO: 4/2/2018 populate gallery items here with picasso
}
}
#Override
public int getItemCount() {
return itemList.size();
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
}
I'm confused how to make the header stick and also what to do for getItemViewType method.
Is this the right way to approach this?
Can anyone help out? Thanks.

For this lay out i suggest better option is use this header view
https://github.com/edubarr/header-decor

To make things simple i suggest you to look into this library
In your XML Place RecylerView into StickyHeaderView,choose horizontal or vertical orientation for your RecylerView
<tellh.com.stickyheaderview_rv.StickyHeaderView
android:id="#+id/stickyHeaderView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:scrollbars="vertical" />
</tellh.com.stickyheaderview_rv.StickyHeaderView>
Create data bean class for each item type in RecyclerView. They should extend DataBean. Override the method
public boolean shouldSticky() to decide whether the item view should be suspended on the top.
public class User extends DataBean {
private String login;
private int id;
private String avatar_url;
private boolean shouldSticky;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.item_user;
}
public void setShouldSticky(boolean shouldSticky) {
this.shouldSticky = shouldSticky;
}
// Decide whether the item view should be suspended on the top.
#Override
public boolean shouldSticky() {
return shouldSticky;
}
}
public class ItemHeader extends DataBean {
private String prefix;
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
#Override
public boolean shouldSticky() {
return true;
}
}
Create ViewBinder to bind different type views with specific data beans. As you see, provideViewHolder(View itemView) corresponds for onCreateViewHolder in RecyclerView, and bindView corresponds for onBindViewHolder in RecyclerView.
public class ItemHeaderViewBinder extends ViewBinder<ItemHeader, ItemHeaderViewBinder.ViewHolder> {
#Override
public ViewHolder provideViewHolder(View itemView) {
return new ViewHolder(itemView);
}
#Override
public void bindView(StickyHeaderViewAdapter adapter, ViewHolder holder, int position, ItemHeader entity) {
holder.tvPrefix.setText(entity.getPrefix());
}
#Override
public int getItemLayoutId(StickyHeaderViewAdapter adapter) {
return R.layout.header;
}
static class ViewHolder extends ViewBinder.ViewHolder {
TextView tvPrefix;
public ViewHolder(View rootView) {
super(rootView);
this.tvPrefix = (TextView) rootView.findViewById(R.id.tv_prefix);
}
}
}
Instantiate StickyHeaderViewAdapter for RecyclerView and register ViewBinders for each item types.
rv = (RecyclerView) findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
List<DataBean> userList = new ArrayList<>();
adapter = new StickyHeaderViewAdapter(userList)
.RegisterItemType(new UserItemViewBinder())
.RegisterItemType(new ItemHeaderViewBinder());
rv.setAdapter(adapter);

Related

How to display multiple objects type in RecyclerView?

I am creating Android app, using room database.
I have two tables DogsTable:
#PrimaryKey(autoGenerate = true)
int dog_id;
String dogName;
and CatsTable (both tables have constructor and getter methods ):
#PrimaryKey(autoGenerate = true)
int cat_id;
String catName;
1- How to display in one RecyclerView two different object type
ArrayList<DogsTable> dog_list;
ArrayList<CatsTable> cat_list;
I am getting the values of dog_list and cat_list from ViewModel Query as show in MainActivity.class.
2- How to fix getItemCount() method? I don't know how to return two different object cat_list.size(); and dog_list.size();
3- Also in onBindViewHolder() method I don`t know how to get cat_list values to display them in UI?
4- Another problem is in swapToDelete() Method in MainActivity.class, I can get the dog id to delete it, but I can not get the cat id to delete it, how can I get the cat id ?
5- How can I display (dog1,dog2 , dog3) as show in first image? (i inserted the value manually in the first image just to show how i want to display them )
Existing Output as below:
My code
MainActivity.java
public class MainActivity extends AppCompatActivity implements MainActivityAdapter.ItemClickListener {
MyViewModel viewModel;
MainActivityAdapter adapter;
RecyclerView recyclerView;
LinearLayoutManager layoutManager;
Button btn_addDog, btn_addCat;
EditText et_addDogName, et_addCatName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
actionButton();
buildRecyclerView();
setUpViewModel_dogs();
swapToDelete_dog();
}
private void initViews() {
et_addDogName = findViewById(R.id.addDogNameET_xml);
et_addCatName = findViewById(R.id.addCatNameET_xml);
}
public void actionButton() {
btn_addDog = findViewById(R.id.AddDog_btn_xml);
btn_addCat = findViewById(R.id.AddCat_btn_xml);
btn_addDog.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
insertDog();
}
});
btn_addCat.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
insertCat();
}
});
}
private void buildRecyclerView() {
recyclerView = findViewById(R.id.recyclerView_id);
adapter = new MainActivityAdapter(this, this);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
}
// Query
public void setUpViewModel_dogs() {
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.getAllDogs().observe(this, new Observer<List<DogsTable>>() {
#Override
public void onChanged(#Nullable List<DogsTable> dogsTables) {
adapter.setDog_list((ArrayList<DogsTable>) dogsTables);
}
});
}
public void setUpViewModel_cats(){
viewModel.getAllCats().observe(this, new Observer<List<CatsTable>>() {
#Override
public void onChanged(#Nullable List<CatsTable> catsTables) {
adapter.setCat_list((ArrayList<CatsTable>) catsTables);
}
});
}
// Add
public void insertDog() {
String dogName = String.valueOf(et_addDogName.getText()).trim();
DogsTable obj_dog = new DogsTable(dogName);
viewModel.insertDog(obj_dog);
Toast.makeText(this, "Dog Added", Toast.LENGTH_SHORT).show();
}
public void insertCat() {
String catName = String.valueOf(et_addCatName.getText());
CatsTable obj_cat = new CatsTable(catName);
viewModel.insertCat(obj_cat);
Toast.makeText(this, "cat Added", Toast.LENGTH_SHORT).show();
}
// Delete
public void swapToDelete_dog() {
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
List<DogsTable> dog_pos = adapter.getDog_list();
viewModel.deleteDog(dog_pos.get(viewHolder.getAdapterPosition()));
}
}
).attachToRecyclerView(recyclerView);
}
public void swapToDelete_cat() {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int item_id = item.getItemId();
if (item_id == R.id.menu_add) {
Intent in = new Intent(this, Add.class);
startActivity(in);
}
return super.onOptionsItemSelected(item);
}
#Override
public void onItemClickListener(int pet_id) {
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/addDogNameET_xml"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:hint="add Dog name" />
<Button
android:id="#+id/AddDog_btn_xml"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="add" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/addCatNameET_xml"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:hint="add Cat name" />
<Button
android:id="#+id/AddCat_btn_xml"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="add" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MissingConstraints" />
</LinearLayout>
MainActivityAdapter.java
public class MainActivityAdapter extends RecyclerView.Adapter<MainActivityAdapter.MyViewHolder> {
Context mContext;
ArrayList<DogsTable> dog_list;
ArrayList<CatsTable> cat_list;
ItemClickListener mItemClickListener;
public MainActivityAdapter(Context context , ItemClickListener itemClickListener) {
this.mContext = context;
this.mItemClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClickListener(int pet_id);
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(mContext).inflate(R.layout.activity_main_adapter, viewGroup, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
DogsTable dog_pos = dog_list.get(position);
// CatsTable catsTable = cat_list.get(position);
holder.dogName.setText(String.valueOf(dog_pos.getDogName()));
// holder.catName.setText(String.valueOf(catsTable.getCatName()));
}
#Override
public int getItemCount() {
if (dog_list == null ) {
return 0;
} else {
return dog_list.size();
}
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener , ItemClickListener {
TextView dogName;
TextView catName;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
dogName = itemView.findViewById(R.id.dogName_xml);
catName = itemView.findViewById(R.id.catName_xml);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int pet_id = dog_list.get(getAdapterPosition()).getDogs_id();
mItemClickListener.onItemClickListener(pet_id);
}
#Override
public void onItemClickListener(int pet_id) {
int pos = dog_list.get(getAdapterPosition()).getDogs_id();
mItemClickListener.onItemClickListener(pet_id);
}
}
public void setDog_list(ArrayList<DogsTable> dog_list) {
this.dog_list = dog_list;
notifyDataSetChanged();
}
public ArrayList<DogsTable> getDog_list() {
return dog_list;
}
public void setCat_list(ArrayList<CatsTable> cat_list) {
this.cat_list = cat_list;
}
}
activity_main_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dogs: " />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/dogName_xml"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cats: " />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="#+id/catName_xml"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
To support different view types, RecyclerView.Adapter provides a useful method int getItemViewType(int position):
Return the view type of the item at position for the purposes of view recycling.
The default implementation of this method returns 0, making the assumption of a single view type for the adapter. Unlike ListView adapters, types need not be contiguous. Consider using id resources to uniquely identify item view types.
Then, in onCreateViewHolder you can see that a second parameter is int viewType which comes from the method int getItemViewType(int position). Based on that, you can instantiate a ViewHolder you need, e.g. DogViewHolder or CatViewHolder.
But what about storing multiple view models in a single adapter and defining which ViewHolder type should be actually instantiated? Here are two most popular approaches:
Declaring multiple containers for multiple types and defining a custom logic for getItemViewType method, e.g. all odd numbers will go in the dogs' list and even numbers will go in the cats' list (or any other method, but beware that you will have to cope with different lists' sizes and all the view types you need). Also, getItemsCount should be overriden appropriately (return list1.size() + list2.size + ... + listN.size();)
Put all the view models in a single list and perform some kind of attributes checks: either it will be some property or the type itself (not recommended for scalability reasons). Then your code will look like this:
public int getItemViewType(int position) {
CommonParentForUpcasting item = items.get(position);
if (item instanceOf Dog) { // or something like item.type == Animal.CAT
return R.id.holder_dog;
} else {
return R.id.holder_cat;
}
}
If you want to come up with a second solution, this solution should suit you well.
Also, make sure to check this StackOverflow answer.

Create curved layout for Android Wearable Recycler View

I am trying to create a curved Wearable Recycler view similar to the one given in below link: https://developer.android.com/training/wearables/ui/lists.html
But I don't see curved layout and all the text comes in a single line .
Can anyone help me how to create a curved Wearable Recycler view . The below is the code fragment. Please let me know if something went wrong in the below code:
My Layout is below:
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.WearableRecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
>
</android.support.wearable.view.WearableRecyclerView>
In my fragment I am using the below code for curved layout:
InformationAdapter informationAdapter = new InformationAdapter(dataSet, images,MenuActivity.this );<br>
wearableRecyclerView.setAdapter(informationAdapter); <br>
wearableRecyclerView.setCenterEdgeItems(true);<br>
wearableRecyclerView.setLayoutManager(new CurvedChildLayoutManager(getActivity()));<br>
wearableRecyclerView.setCircularScrollingGestureEnabled(true);
wearableRecyclerView.setBezelWidth(0.5f);
wearableRecyclerView.setScrollDegreesPerScreen(90);
My Adapter is as below:
public class InformationAdapter extends
WearableRecyclerView.Adapter<InformationAdapter.ViewHolder> {
private static final String TAG = "CustomRecyclerAdapter";
private String[] mDataSet;
private int[] mImages;
private ItemClickListener itemClickListener;
// Custom Controller used to instruct main activity to update {#link Notification} and/or
// UI for item selected.
public static class ViewHolder extends WearableRecyclerView.ViewHolder {
private final TextView mTextView;
private final ImageView menuImageIcon;
public ViewHolder(View view) {
super(view);
mTextView = (TextView) view.findViewById(R.id.textView);
menuImageIcon = (ImageView)view.findViewById(R.id.menu_image);
}
#Override
public String toString() { return (String) mTextView.getText(); }
}
public InformationAdapter(String[] dataSet,int[] mImages,ItemClickListener itemClickListener) {
mDataSet = dataSet;
this.mImages = mImages;
this.itemClickListener = itemClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recycler_row_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.mTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// mController.itemSelected(mDataSet[position]);
itemClickListener.onItemSelected(mDataSet[position]);
}
});
// Replaces content of view with correct element from data set
viewHolder.mTextView.setText(mDataSet[position]);
viewHolder.menuImageIcon.setImageResource(mImages[position]);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataSet.length;
}
}
Row Item layout for Adapter:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingTop="#dimen/recycler_row_padding"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="#drawable/ic_n_white_48dp"
android:id="#+id/menu_image"/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textSize="#dimen/recycler_row_text_size"
android:id="#+id/textView"
/>
</LinearLayout>
I faced with the same problem. Changing
android:layout_height="wrap_content"
to
android:layout_height="match_parent"
in WearableRecyclerView worked for me. Hope it helps.

Set image in cardview one by one from drawable

I am trying to add images in a cardview from drawable and text one by one using a recyclerview. say there are 10 images in my drawable i want to use only 5 of them. So how to do that ?
here is my cardview :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/placeCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
card_view:cardCornerRadius="#dimen/card_corner_radius">
<ImageView
android:id="#+id/placeImage"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop" />
<!-- Used for the ripple effect on touch -->
<LinearLayout
android:id="#+id/mainHolder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:orientation="horizontal" />
<LinearLayout
android:id="#+id/placeNameHolder"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_gravity="bottom"
android:orientation="horizontal">
<TextView
android:id="#+id/placeName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="left"
android:paddingLeft="10dp"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#android:color/white" />
</LinearLayout>
</android.support.v7.widget.CardView>
here is my recyclerview adapter :
public class SubPlaceAdapter extends RecyclerView.Adapter<SubPlaceRecyclerViewHolder>{
String ImageUri;
#Override
public SubPlaceRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_places, null);
SubPlaceRecyclerViewHolder viewHolder = new SubPlaceRecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(SubPlaceRecyclerViewHolder holder, int position) {
// holder.subPlaceImage
}
#Override
public int getItemCount() {
return 0;
}
}
my view holder :
public class SubPlaceRecyclerViewHolder extends RecyclerView.ViewHolder {
protected ImageView subPlaceImage;
protected TextView subPlaceTitle;
public SubPlaceRecyclerViewHolder(View view) {
super(view);
this.subPlaceImage = (ImageView) view.findViewById(R.id.placeImage);
this.subPlaceTitle = (TextView) view.findViewById(R.id.placeName);
}
}
thanks for the help :)
Step 1. First create a Model
public class ImageModel {
int imageId;
String aboutText;
public int getImageId() {
return imageId;
}
public void setImageId(int imageId) {
this.imageId = imageId;
}
public String getAboutText() {
return aboutText;
}
public void setAboutText(String aboutText) {
this.aboutText = aboutText;
}
}
Step 2. Create a method which return arraylist of imageModel in your fragment/activity from where you set the adapter
private ArrayList<ImageModel> setImageData(){
ArrayList<ImageModel> projectList=new ArrayList<>();
ImageModel imageModel=new ImageModel();
imageModel.setImageId(R.mipmap.ic_star_fill);
imageModel.setAboutText("RandomText");
projectList.add(imageModel);
ImageModel imageModel1=new ProjectModel();
projectModel.setImageId(R.mipmap.ic_star_fill);
projectModel.setAboutText("RandomText");
projectList.add(projectModel);
return projectList;
}
Step 3. Create constructor in your adapter which takes ArrayList as an argument
public SubPlaceAdapter(ArrayList<ImageModel> mImageList) {
this.mActivity = mActivity;
this.mImageList = mImageList);
}
Step 4. Set your adapter in your fragment/ activity.
mSubPlaceAdapter = new SubPlaceAdapter(setImageData());
Step 5. Set your item in on BindView Holder
#Override
public void onBindViewHolder(SubPlaceRecyclerViewHolder holder, int position) {
ImageModel imageModel= mImageList.get(position)
holder.subPlaceImage.setImageResource(imageModel.getImageId());
}
#Override
public int getItemCount() {
return mImageList.size();
}
This code will give you the idea how to do it.Fill free to modify this answer.

Add a row to an empty recyclerview on execution time

I have an activity with an AutoCompleteTextView and a button, and below it, a hidden RecyclerView, that starts empty (with no rows).
With the AutoCompleteTextView, I select an object and what I want is, when I click the button, to add that object to the RecyclerView(and turn the visibility on for the recycler).
So far, I've managed to add the object to the recycler's DataSet, but it won't show any row on notifyDataSetChanged().
The layout:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:id="#+id/ib_add"
android:src="#drawable/ic_add_black"
android:onClick="onAddClick"/>
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/actv_input"
android:layout_toLeftOf="#+id/ib_add"
android:layout_toStartOf="#+id/ib_add"
android:hint="#string/name_hint"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
The Activity (just the relevant functions):
#Bind(R.id.rv) RecyclerView rv;
ArrayList<Ing> ings = new ArrayList<>();
ArrayList<Ing> selectedIngs = new ArrayList<>();
private void setupRecyclers() {
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(new RecyclerViewAdapter(selectedIngs));
}
public void onAddClick(View view) {
Ing ing = ings.get(selectedPosition);
rv.setVisibility(View.VISIBLE);
selectedIngs.add(ing);
((RecyclerViewAdapter)rv.getAdapter()).addIng(ing);
}
The RecyclerViewAdapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RViewHolder> {
ArrayList<Ing> ings;
public RecyclerViewAdapter(ArrayList<Ing> ings) {
this.ings = ings;
}
#Override
public RViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_ing, parent, false);
return new RViewHolder(row);
}
#Override
public void onBindViewHolder(RViewHolder holder, int position) {
Ing ing = ings.get(position);
holder.bindToView(ing);
}
#Override
public int getItemCount() {
return ings.size();
}
public void addIng(Ing ing) {
ings.add(ing);
notifyDataSetChanged();
}
public void setDataSet(ArrayList<Ing> ings) {
this.ings = ings;
notifyDataSetChanged();
}
}
The RecyclerViewHolder:
public class RViewHolder extends RecyclerView.ViewHolder {
Ing ing;
ImageView ivIcon;
TextView tvName;
ImageButton ibRemove;
TextView tvPercentage;
EditText etPercentage;
public RViewHolder(View row) {
super(row);
bindFields(row);
}
private void bindFields(View view) {
ivIcon = (ImageView) view.findViewById(R.id.iv_icon_type);
tvName = (TextView) view.findViewById(R.id.tv_ing);
ibRemove = (ImageButton) view.findViewById(R.id.btn_remove);
tvPercentage = (TextView) view.findViewById(R.id.tv_percentage);
etPercentage = (EditText) view.findViewById(R.id.et_percentage);
}
public void bindToView(Ing ing){
this.ing = ing;
tvName.setText(ing.getName());
ivIcon.setImageResource(R.drawable.icon);
tvName.setVisibility(View.VISIBLE);
ivIcon.setVisibility(View.VISIBLE);
ibRemove.setVisibility(View.VISIBLE);
tvPercentage.setVisibility(View.VISIBLE);
etPercentage.setVisibility(View.VISIBLE);
}
}
What am I missing?
Thanks!
Solved!
The first part, the recycler not showing even with an element inside, was fixed by the 23.2.0 support library's update, that introduced auto measurement for recyclerviews. Before that, if you had a recycler within a relative within a nested, it did some funny business and never initialized the rows inside the recycler.
The second part, the button not adding the row, was because even if you have some onclick event set in your image button, it looks that you have to put android:clickable = true or else it won't work.

RecyclerView not scrolling to the bottom

I followed the recyclerview guidelines and built one for the app I am making, but it does not scroll to the bottom for some reason. I compared it with google code snippets, as well as other code snippets online and can't see the difference. I have posted a picture and the code I am using. I am using tabs, therefore the recyclerview is populated in a fragment.
What the app looks like:
http://imgur.com/H5uOLFR
the adapter class:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Group> groups;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView groupName;
public TextView groupDate;
public TextView groupLocation;
public TextView className;
public ViewHolder(View v) {
super(v);
groupName = (TextView) v.findViewById(R.id.groupName);
groupDate = (TextView) v.findViewById(R.id.groupDate);
groupLocation = (TextView) v.findViewById(R.id.groupLocation);
className = (TextView) v.findViewById(R.id.className);
}
}
/*
* TODO: finish this method
*/
public void add(int position, String item) {
notifyItemInserted(position);
}
public void remove(String item) {
int position = groups.indexOf(item);
groups.remove(position);
notifyItemRemoved(position);
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Group> groupsList) {
groups = groupsList;
Log.d("TEST", "Number of Groups: " +
Integer.toString(groups.size()));
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.group_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
final Group group = groups.get(position);
// holder.groupName.setText(group.getName());
holder.groupName.setText(group.getName());
holder.groupDate.setText(group.getFormattedDate());
holder.groupLocation.setText(group.getLocation());
holder.className.setText(group.getParent().getName());
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return groups.size();
}
}
The Fragment class:
public class groupsFragment extends Fragment implements GroupLeaver, GroupRetriever {
private RecyclerView rv;
private List<Group> groups;
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
Log.d("TEST", "Entered onCreate");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AppMain.getController().retrieveGroups(groupsFragment.this);
Log.d("TEST", "Entered onCreateView");
View rootView = inflater.inflate(R.layout.groups_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.recyclerView);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
Log.d("TEST", "Size of LIST: " + Integer.toString(groups.size()));
MyAdapter adapter = new MyAdapter(groups);
rv.setAdapter(adapter);
return rootView;
}
#Override
public void onMyGroupsFound(List<Group> groups) {
Log.d("TEST", "Entered onMyGroupsFound");
Logg.info(this.getClass(), "Found %d groups for member %s", groups.size(), User.getCurrentUser().getDisplayName());
this.groups = groups;
}
#Override
public void onGroupLeft(Group oldGroup) {
}
#Override
public void onGroupLeftFailed(Group group, ParseException e) {
}
}
The xml layout for the recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#null"/>
</FrameLayout>
The xml layout for the recyclerview items:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="horizontal">
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="3"
android:orientation="vertical">
<TextView
android:id="#+id/groupName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Name"
/>
<TextView
android:id="#+id/groupDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Group Date"
/>
<TextView
android:id="#+id/groupLocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Group Location"
/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/className"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="right"
android:text="Class Name"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
You can use these lines to scroll recyclerview to:
list.add(0, group);
adapter.notifyItemInserted(0);
recyclerview.scrollToPosition(0);
Thanks to everyone who responded, but turns out the problem was the version of RecyclerView I was compiling.
Previously I was compiling this
compile 'com.android.support:recyclerview-v7:22.0.0'
But I changed it to this and it worked
compile 'com.android.support:recyclerview-v7:22.2.0'
Credits to #roi divon for the answer: CoordinatorLayout with RecyclerView & CollapsingToolbarLayout
Maybe adding these lines to the recyclerView will do:
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"
This is my recyclerView which is working:
<android.support.v7.widget.RecyclerView
android:id="#+id/menuRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbars="vertical"/>
I am not sure but I think problem might be Framelayout You can try with Linearlayout instead of Framelayout in your xml layout for the recyclerview items

Categories

Resources