Why isn't my DiffUtil with RecyclerView working? - android

I'm trying to create a simple DiffUtil Adapter to work with a RecyclerView and nothing shows up (I only get a blank activity). Here is the code:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private MyAdapter mAdapter;
private ArrayList<User> myDataset;
private RecyclerView mRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter();
myDataset = new ArrayList<User>();
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
myDataset.add(new User("User1"));
myDataset.add(new User("User2"));
myDataset.add(new User("User3"));
mRecyclerView.setAdapter(mAdapter);
mAdapter.updateList(myDataset);
}
}
Here is MyAdapter.java:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private AsyncListDiffer<User> mAsyncListDiffer;
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView singleItemTextView;
public View layout;
public ConstraintLayout constraintLayout;
public MyViewHolder(View v) {
super(v);
layout = v;
singleItemTextView = (TextView) v.findViewById(R.id.singleItemTextView);
constraintLayout = (ConstraintLayout) v.findViewById(R.id.constraintLayout);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter() {
DiffUtil.ItemCallback<User> diffUtilCallback = new DiffUtil.ItemCallback<User>() {
#Override
public boolean areItemsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.getUserId().equals(oldUser.getUserId());
}
#Override
public boolean areContentsTheSame(#NonNull User newUser, #NonNull User oldUser) {
return newUser.equals(oldUser);
}
};
mAsyncListDiffer = new AsyncListDiffer<>(this, diffUtilCallback);
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_text_view, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
User user = mAsyncListDiffer.getCurrentList().get(position);
holder.singleItemTextView.setText(user.getUserId());
}
#Override
public int getItemCount() {
return mAsyncListDiffer.getCurrentList().size();
}
public void updateList(ArrayList<User> newList) {
mAsyncListDiffer.submitList(newList);
}
}
Here is User.java:
public class User {
private String mUserId;
public User(String userId) {
mUserId = userId;
}
public String getUserId() {
return mUserId;
}
}
Here are the XML files:
acivity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="4dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:background="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
and here is single_text_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="81dp">
<TextView
android:id="#+id/singleItemTextView"
android:layout_width="78dp"
android:layout_height="78dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
I know that DiffUtil is supposed to compare 2 different lists and here I only set up the initial list, but still, shouldn't it at least display the first list (with 3 users in this case)?

Set LayoutManager with Recyclerview
// add data on list
private ArrayList<User> myDataset=new ArrayList;
myDataset.add(new User("abc"));
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
LayoutManager layoutManager=new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
MyAdapter myAdapter=new MyAdapter();
mAdapter.updateList(myDataset);
mRecyclerView.setAdapter(mAdapter);

Do you check if your getItemCount() method returns more than 0 ?
If it is, you should look at your item view. Try to remove constraints on this view first to see if anything appears on the screen.

Related

Unable to show list in RecyclerView

I am trying to show the list in RecyclerView.
but after setting adapter only Adapter constructor getting called after that nothing happens
Below is the code of Adapter
public class ChildNameAdpator extends RecyclerView.Adapter<ChildNameAdpator.ViewHolder> {
List<ChildDatum> arrayList;
public ChildNameAdpator(List<ChildDatum> arrayListChildName) {
arrayList = new ArrayList<>();
arrayList = arrayListChildName;
}
#NonNull
#Override
public ChildNameAdpator.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LinearLayout layoutRowPermissionCount = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.row_child_name_layout, parent, false);
return new ViewHolder(layoutRowPermissionCount);
}
#Override
public void onBindViewHolder(#NonNull ChildNameAdpator.ViewHolder holder, int position) {
holder.mTvChildName.setText(arrayList.get(position).getChildName());
}
#Override
public int getItemCount() {
return arrayList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
AutoResizeTextView mTvChildName;
LinearLayout mLinearLayoutChild;
AutoResizeTextView imageButtonDeleteChildRow;
ViewHolder(#NonNull View itemView) {
super(itemView);
Log.d(TAG, "ViewHolder: ");
mTvChildName = itemView.findViewById(R.id.tv_row_child_name);
mLinearLayoutChild = itemView.findViewById(R.id.ll_row_child_name);
}
}
}
I am calling this adapter with below code
mRecyclerviewChildName = findViewById(R.id.rv_child_name_parental_control);
mRecyclerviewChildName.setLayoutManager(new LinearLayoutManager(this));
mCurrentChildsList.add(new ChildDatum("11", "ty8902", "3333", "3333", "333", "2222", "2222", "1222"));
mCurrentChildsList.add(new ChildDatum("12", "ty8902", "3333", "3333", "333", "2222", "2222", "1222"));
mCurrentChildsList.add(new ChildDatum("13", "ty8902", "3333", "3333", "333", "2222", "2222", "1222"));
childNameAdpator = new ChildNameAdpator(mCurrentChildsList);
mRecyclerviewChildName.setAdapter(childNameAdpator);
Below is row layout
<?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">
<TextView
android:id="#+id/tv_row_child_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
EDIT: Added Recyclerview's Parent Layout
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<androidx.cardview.widget.CardView
android:id="#+id/card_view_display_child_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_marginBottom="16dp"
android:padding="8dp"
android:visibility="gone"
app:cardBackgroundColor="#color/colorPrimaryDark"
app:cardCornerRadius="8dp"
app:cardElevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_child_name_parental_control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical">
</androidx.recyclerview.widget.RecyclerView>
<com.lb.auto_fit_textview.AutoResizeTextView
android:id="#+id/ib_add_new_child_name"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:background="#drawable/ic_add_circle_black_24dp"
android:padding="8dp"
android:textAlignment="center"
android:textColor="#color/colorGreyLight"
android:textStyle="bold"
android:visibility="gone" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
After setAdapter only constructor getting called nothing else that's it.
I thought it is due to my Gradle issue and tried on another laptop, the same issue occurred there.
Looking for help
Thanks in advance.
Change Adapter Constructor and try this
public ChildNameAdpator(List<ChildDatum> arrayListChildName) {
arrayList = new ArrayList<>();
arrayList.addAll(arrayList);
}
or
public ChildNameAdpator(List<ChildDatum> arrayListChildName) {
this.arrayList = arrayListChildName;
}
Try this way:
rView=findViewById(R.id.rView);
rView.setHasFixedSize(true);
lManager=new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
rView.setLayoutManager(lManager);
Make sure the following things you have done:
Declared your adapter class as public
Initialised
'mCurrentChildsList' before adding items.
Initialise: mCurrentChildsList = new ArrayList()
You have skipped the LayoutManager.
A LayoutManager is responsible for measuring and positioning item views within a RecyclerView as well as determining the policy for when to recycle item views that are no longer visible to the user.
Set the LayoutManager once you initialized the recycler view.
mRecyclerviewChildName.setLayoutManager(new LinearLayoutManager(this));
Reference : LayoutManager
Adapter Code:
public class ChildNameAdpator extends RecyclerView.Adapter<ChildNameAdpator.ViewHolder> {
private List<ChildDatum> arrayList;
public ChildNameAdpator(List<ChildDatum> arrayListChildName) {
arrayList = arrayListChildName;
}
}
This how your adapter class looks like.
Main Activity.
public class DemoTestActivity extends AppCompatActivity {
RecyclerView mRecyclerviewChildName;
ChildNameAdpator childNameAdpator;
List<ChildDatum> mCurrentChildsList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo_test);
mCurrentChildsList = new ArrayList<>();
mRecyclerviewChildName=(RecyclerView)findViewById(R.id.rv_child_name_parental_control);
mCurrentChildsList.add(new ChildDatum("Mehul"));
mCurrentChildsList.add(new ChildDatum("Mehul 1"));
mCurrentChildsList.add(new ChildDatum("Mehul 2"));
childNameAdpator = new ChildNameAdpator(mCurrentChildsList);
mRecyclerviewChildName.setLayoutManager(new LinearLayoutManager(DemoTestActivity.this, LinearLayoutManager.VERTICAL, false));
mRecyclerviewChildName.addItemDecoration(new DividerItemDecoration(mRecyclerviewChildName.getContext(), DividerItemDecoration.VERTICAL));
mRecyclerviewChildName.setAdapter(childNameAdpator);
}}
Main Layout file
<?xml version="1.0" encoding="utf-8"?>
<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=".DemoTestActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_child_name_parental_control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical">
</androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>
Adapter
public class ChildNameAdpator extends
RecyclerView.Adapter<ChildNameAdpator.ViewHolder> {
List<ChildDatum> arrayList;
public ChildNameAdpator(List<ChildDatum> arrayListChildName) {
arrayList = new ArrayList<>();
arrayList = arrayListChildName;
}
#NonNull
#Override
public ChildNameAdpator.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LinearLayout layoutRowPermissionCount = (LinearLayout) LayoutInflater.from(parent.getContext()).inflate(R.layout.row_child_name_layout, parent, false);
return new ViewHolder(layoutRowPermissionCount);
}
#Override
public void onBindViewHolder(#NonNull ChildNameAdpator.ViewHolder holder, int position) {
holder.mTvChildName.setText(arrayList.get(position).getChildName());
}
#Override
public int getItemCount() {
return arrayList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
TextView mTvChildName;
ViewHolder(#NonNull View itemView) {
super(itemView);
mTvChildName = itemView.findViewById(R.id.tv_row_child_name);
}
}}
Model class
public class ChildDatum {
String ChildName;
public ChildDatum(String sChildName) {
this.ChildName = sChildName;
}
public String getChildName() {
return ChildName;
}
public void setChildName(String childName) {
ChildName = childName;
}}
Finally, I got my mistake.
android:visibility="gone"
VISIBILITY of parent Cardview was GONE due to this onBindViewHolder was not getting called.
When I changed the visibility to VISIBLE it Worked.
Thank you all for your efforts.

RecyclerView does not scroll & Won't display large numbers

I am having a bit trouble with my RecyclerView. If my adapter list have more than 20 items, the recyclerview shows nothing. Anything <20 is ok, and the items are displayed. Also, I can't scroll on the recyclerView.
RecyclerView creation in Fragment:
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);
myAdapter = new MyAdapter();
myAdapter.setList(myList); //ArrayList<MyObject>
recyclerView.setAdapter(myAdapter);
My Adapter:
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
private final ArrayList<MyObject> myList = new ArrayList<MyObject>();
public MyAdapter() {}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_item, parent, false);
return new MyAdapter(v);
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
holder.bind(myList.get(position));
}
#Override
public int getItemCount() {
return myList.size();
}
public void setList(ArrayList<MyObject> newList) {
myList.clear();
myList.addAll(newList);
notifyDataSetChanged();
}
}
and here is my viewholder:
public class CountryViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
private MyObject object;
public CountryViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.my_holder_textview);
}
public void bind(#Nullable MyObject object){
this.object = object;
if(pbject == null)
textView.setText("Error. Could not load name.");
else
textView.setText(object.getName());
}
}
myitem.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/my_holder_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=""
android:layout_marginBottom="4dp"
android:textSize="24sp"
android:gravity="center"/>
</LinearLayout>
Fragment layout where I have the recyclerView:
<androidx.constraintlayout.widget.ConstraintLayout 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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Any suggestions?
EDIT:
Changing the layout from ConstraintLayout to LinearLayout, the recyclerview will run fine as it should. So the culprit here is the Constraintlayout. I would like to keep the constraintlayout, but I can't figure out how to make it work yet.
Instead of:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
Try:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/myRecyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
I can see that you have an error in onCreateViewHolder, it should return MyViewHolder and not a MyAdapter.
Also the setHasFixedSize(true) could be an issue here because your children might not change in size if this has to be true(find more information on SO).

RecyclerView does not display items

I am using RecyclerView in Android with a model class that has title and details. Nothing is showing. Even after log inside Adapter nothing is shown in Android Monitor.
MainActivity.class
public ArrayList<Menu> menu_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_menu);
initUi();
}
public void initUi(){
RecyclerView menu_recycler = (RecyclerView) findViewById(R.id.main_menu_recycler_view);
//set the layout manager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation( linearLayoutManager.VERTICAL );
menu_recycler.setLayoutManager( linearLayoutManager );
//set adapter
MainMenuAdapter mainMenuAdapter = new MainMenuAdapter( getMenulist() );
menu_recycler.setAdapter( mainMenuAdapter );
}
public ArrayList<Menu> getMenulist() {
menu_list = new ArrayList<Menu>();
menu_list.add( new Menu("About Us", " Learn more about our values, mission and vision ") );
menu_list.add( new Menu("Services ", " In implementing its mandate, the Agency will provide the following to its external and internal customers:\n"));
menu_list.add( new Menu("Stakeholders", " Who are the key players, Find out more") );
menu_list.add( new Menu("Learn about Counterfeits", "Gain more insight on counterfeit products"));
return menu_list;
}
and here is my adapter
public class MainMenuAdapter extends RecyclerView.Adapter<MainMenuAdapter.MyViewHolder> {
public List<Menu> list_of_menus;
public MainMenuAdapter( List<Menu> list_of_menus){
this.list_of_menus = list_of_menus;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row,parent, false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Menu menu = list_of_menus.get(position);
Log.e("MENU IN ADAPTER TITLE", menu.title);
holder.title_text.setText( menu.title );
holder.details_text.setText( menu.details );
}
#Override
public int getItemCount() {
return 0;
}
/*
View Holder class
* */
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView title_text, details_text;
public MyViewHolder(View itemView) {
super(itemView);
title_text = (TextView) itemView.findViewById(R.id.menu_title);
details_text = (TextView) itemView.findViewById(R.id.menu_details);
}
}
}
And the Model Class
public class Menu {
public String title, details;
public Menu(String title, String details){
this.details = details;
this.title = title;
}
}
And the layout file main_activity
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.maos.aca.MainMenuActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="334dp"
android:layout_height="453dp" app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="8dp" android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent" android:layout_marginRight="8dp"
app:layout_constraintRight_toRightOf="parent" android:id="#+id/main_menu_recycler_view"
android:scrollbars="vertical"/>
</android.support.constraint.ConstraintLayout>
And finally the row
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/menu_title"
android:textStyle="bold"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:id="#+id/menu_details"/>
</LinearLayout>
I know this question has been asked before, but none of the answers helped me out.I'll appreciate any lead.
You need to change the getItemCount() method to this:
#Override
public int getItemCount() {
return list_of_menus.size();
}
The RecyclerView will not display any elements if you are reporting that its size is zero.
Change this:
#Override
public int getItemCount() {
return 0;
}
To this:
#Override
public int getItemCount() {
return list_of_menus.size();
}

Horizontal recyclerview into vertical recyclerview at specific position

I want to insert/show horizontal recyclerview into specific position (at this example position:1)
Vertical recyclerview - displays TextView + shape (rectange)
Horizontal recyclerview - displays ImageViews (next to each other)
.XML's
horizontal_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/horizontal_recyclerview"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="2dp"
android:padding="0dp"/>
<android.support.constraint.ConstraintLayout 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:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.mkalejs.training.MainActivity">
vertical_layout.xml
<android.support.v7.widget.RecyclerView
android:id="#+id/vertical_recyclerview"
android:layout_width="368dp"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="2dp"
android:padding="0dp"/>
</android.support.constraint.ConstraintLayout>
vertical_layout_item.xml
<EditText
android:id="#+id/lbl_url_text"
android:layout_width="100dp"
android:layout_height="50dp"
android:background="#android:color/transparent"
android:inputType="textPersonName"
android:padding="5dp"
android:layout_gravity="center"
android:text="Name" />
<View
android:id="#+id/rectangle"
android:layout_width="195dp"
android:layout_height="100dp"
android:background="#drawable/rectangle" />
horizontal_layout_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:visibility="visible"
android:weightSum="1">
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/img_horizontal_slider"
android:layout_width="33dp"
android:layout_height="33dp"
android:adjustViewBounds="true"
android:visibility="visible" />
</LinearLayout>
There might be a small misunderstanding in recyclerview concept. I'm not sure where I can call horizontal_recyclerview" to not return it as a null (as I am now) and populate it with data. Is the XML structure wrong? Feel free to update code parts.
THIS SHOULD BE OKAY
MainActivity.class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.vertical_layout);
ArrayList<PictureData> bundleOfData = prepareData();
RecyclerView rv = (RecyclerView) findViewById(R.id.vertical_recyclerview);
VerticalAdapter adapter = new VerticalAdapter(bundleOfData, this);
rv.setAdapter(adapter);
//rv.setNestedScrollingEnabled(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
rv.setLayoutManager(layoutManager);
}
VerticalAdapter.class
public class VerticalAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private ArrayList<PictureData> pictures;
Context context;
public VerticalAdapter(ArrayList<PictureData> pictures, Context context)
{
this.pictures = pictures;
this.context = context;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView;
switch (viewType) {
case 1:
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_layout_item, parent, false);
return new HorizontalViewHolder(itemView);
default:
itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.vertical_layout_item, parent, false);
return new VerticalViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()){
case 1:
HorizontalViewHolder hVh = (HorizontalViewHolder) holder;
HorizontalAdapter horizontal_adapter = new HorizontalAdapter(pictures, context);
hVh.horizontal_rec.setAdapter(horizontal_adapter);
break;
default:
VerticalViewHolder vVh = (VerticalViewHolder) holder;
vVh.textView.setText(pictures.get(position).getPictureUrl());
break;
}
}
#Override
public int getItemCount() {return pictures.size();}
#Override
public int getItemViewType(int position) {
if(position == 1){
return 1;
}else{
return 0;
}
}
}
HorizontalViewHolder.class
I GET A ERROR HERE. OBVIOUSLY, I DON'T HAVE (img_horizontal_slider) IN HORIZONTAL_LAYOUT, but putting ImageView + RecyclerView in one layout file and call here would feel wrong (?)
public class HorizontalViewHolder extends RecyclerView.ViewHolder{
public ImageView imagePositionInLayout;
public RecyclerView horizontal_rec;
public HorizontalViewHolder(View itemView) {
super(itemView);
LinearLayoutManager layoutManager = new LinearLayoutManager(itemView.getContext(), LinearLayoutManager.HORIZONTAL, false);
horizontal_rec = itemView.findViewById(R.id.vertical_recyclerview);
imagePositionInLayout = itemView.findViewById(R.id.img_horizontal_slider);
horizontal_rec.setLayoutManager(layoutManager);
}
public ImageView getView() {
return imagePositionInLayout;
}
}
HorizontalAdapter.class
ublic class HorizontalAdapter extends RecyclerView.Adapter<HorizontalViewHolder> {
private ArrayList<PictureData> pictures;
Context context;
public HorizontalAdapter(ArrayList<PictureData> pictures, Context context) {
this.pictures = pictures;
this.context = context;
}
#Override
public HorizontalViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.horizontal_layout_item, parent, false);
return new HorizontalViewHolder(view);
}
#Override
public void onBindViewHolder(HorizontalViewHolder holder, int position)
{
Picasso.Builder builder = new Picasso.Builder(context);
Picasso picasso = builder.build();
picasso
.load("http://nuclearpixel.com/content/icons/2010-02-09_stellar_icons_from_space_from_2005/earth_128.png")
.placeholder(R.mipmap.ic_launcher_round)
.into(holder.imagePositionInLayout);
}
#Override
public int getItemCount() {
return pictures.size();
}
}
I'm new to Android so I hope people will give some good explanation on what is wrong and how to fix it. Every suggestion will be gladly accepted. I will highly appreciate if someone will actually look into this and explain, because I feel pretty lost right now.

android:staggergridlayout while moving up shuffles

I am using staggered grid layout. the following is the code:
StaggeredGridLayoutManager glm= new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
glm.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
I am using GAP_HANDLING_NONE to avoid images swapping from one column to other.
When I start the app, the beginning of the screen is:
After scrolling down to bottom and when I return to the top. randomly the following three images show the layout (it keeps varying)
Staggered grids are likely to have gaps at the edges of the layout. To avoid these gaps, StaggeredGridLayoutManager can offset spans independently or move items between spans. You can control this behavior via setGapStrategy(int):
StaggeredGridLayoutManager sGrid = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
sGrid.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
I hope this will help a buddy.
Try below code.
Add this Override methode in your Adapter
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
If this solution is not work for you!
Try below solution
I am using StaggeredGridLayout for getting all gallery images and it's working fine for me.
- Main Activity
/*Init Gallery Photos RecyclerView*/
gallerySglm = new StaggeredGridLayoutManager(2, RecyclerView.VERTICAL);
gallerySglm.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
binding.rvGalleryImg.setLayoutManager(gallerySglm);
galleryPhotosAdapter = new GalleryPhotosAdapter(context, galleryPhotoArrayList);
binding.rvGalleryImg.setAdapter(galleryPhotosAdapter);
galleryPhotosAdapter.notifyDataSetChanged();
/*End Init Gallery Photos RecyclerView*/
- Item Layout
Add ImageView inside ConstraintLayout
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mainCard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/main_bg"
app:cardCornerRadius="#dimen/_5sdp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="false"
android:layout_margin="#dimen/_2sdp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/clMain"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/img"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitXY"
android:visibility="visible"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>
- Adapter
public class GalleryPhotosAdapter extends RecyclerView.Adapter<GalleryPhotosAdapter.ViewHolder> {
private Context context;
private ArrayList<String> arrayList;
private ConstraintSet set = new ConstraintSet();
public GalleryPhotosAdapter(Context context, ArrayList<String> arrayList) {
this.context = context;
this.arrayList = arrayList;
}
#NonNull
#Override
public GalleryPhotosAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
ItemGalleryPhotosBinding binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.item_gallery_photos, parent, false);
return new ViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull final GalleryPhotosAdapter.ViewHolder holder, final int position) {
//Set size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(arrayList.get(position), options);
String ratio = String.format(Locale.getDefault(), "%d:%d", options.outWidth, options.outHeight);
set.clone(holder.binding.clMain);
set.setDimensionRatio(holder.binding.img.getId(), ratio);
set.applyTo(holder.binding.clMain);
//End set size
Glide.with(context)
.load(arrayList.get(position))
.into(holder.binding.img);
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ItemGalleryPhotosBinding binding;
public ViewHolder(ItemGalleryPhotosBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
}
I hope this can help You!
Thank You.
Use this simple solustion for your problem.
StaggeredGridLayoutManager straggerGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
straggerGridLayoutManager .setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
recyclerView.setLayoutManager(straggerGridLayoutManager);
dataList = YourDataList (Your Code for Arraylist);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerAdapter = new DataAdapter(dataList, recyclerView);
recyclerView.setAdapter(recyclerAdapter);
recyclerView.addOnScrollListener(new ScrollListener());
Create class for Custom RecyclerView Scroll Listener.
private class ScrollListener extends RecyclerView.OnScrollListener {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
recyclerView.invalidateSpanAssignments();
}
}
Notice the sample code I provided for you
Images are shown in different proportions based on their dimensions and even some apps show a mixed view of images and videos like Instagram. In the coming tutorial, we will be experiencing such a view where videos are loaded and played with autoplay features when we strolled onto the video view.
When it comes to the implementation technically there is no much difference in regular style of showing images to this staggering view.
Activity_main.Xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="staggered.android.com.staggeredview.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/stagRecycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.constraint.ConstraintLayout>
Recyclerview_row.Xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="#+id/imgView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"/>
</RelativeLayout>
MainActivity.Java
public class MainActivity extends AppCompatActivity {
RecyclerViewAdapter adapter;
ArrayList<Integer> Image;
RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Image = new ArrayList<>(Arrays.asList(
R.drawable.img1,R.drawable.img2,
R.drawable.img3,R.drawable.img4,
R.drawable.img5,R.drawable.img6,
R.drawable.img7,R.drawable.img8,
R.drawable.img9,R.drawable.img10,
R.drawable.img1,R.drawable.img2,
R.drawable.img3,R.drawable.img4,
R.drawable.img5,R.drawable.img6,
R.drawable.img7,R.drawable.img8,
R.drawable.img9)
);
recyclerView = findViewById(R.id.stagRecycleView);
layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerViewAdapter(this, Image);
recyclerView.setAdapter(adapter);
}
}
And finally
RecyclerViewAdapter.Java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
ArrayList<Integer> Image;
Context context;
public RecyclerViewAdapter(Context context, ArrayList<Integer> Image) {
super();
this.context = context;
this.Image = Image;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.recyclerview_row, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.imgview.setImageResource(Image.get(i));
}
#Override
public int getItemCount() {
return Image.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imgview;
public ViewHolder(View itemView) {
super(itemView);
imgview = (ImageView) itemView.findViewById(R.id.imgView);
}
}
}
I hope this will help you ;)

Categories

Resources