Tuesday, January 9, 2018

Custom HorizontalScrollView adapter RecyclerView

Leave a Comment

I'm trying to create an HorizontalScrollView with a RecyclerView, I have my adapter with FirebaseAdapter with my onCreateViewHolder, onDataChanged and its onBindViewHolder, what I'd like to add on my RecyclerView is something like this Image, something like, user only will see 3 items, and the centered zoomed/bigger, someone told me that I have to override getItemViewType, but I do not know how to, could you guide to how to do it?

To make it act like an HorizontalScrollView I've added a CustomLinearLayout like this :

LinearLayoutManager layoutManager =  new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); rv.setLayoutManager(layoutManager); 

What I'd like it to show is like this (each blank rectangle is an item) :

enter image description here

FOR THOSE WHO DON'T UNDERSTAND

I allready have a RecyclerView which acts like HorizontalScrollView BUT I'm not able to make that customizable, to show it like the image from above.

4 Answers

Answers 1

Actually this is a popular thing to implement, so the solution already exists on GitHub - https://github.com/yarolegovich/DiscreteScrollView. It's highly customizable, so you can adjust it for your needs and metrics. Here is an example from that lib:

enter image description here

Answers 2

i have faced something like this but i fixed it from changing it from recylerview to ViewPager it is more smoother and better in performance first the xml layout you will work with the margins and padding , it consists of 4 classes with are shadow transform for the animation you want ,cardFragmentPagerAdapter for the pager adapter , interface cardAdapter for the elevations of the cards and a cardFragment for the layout appearence

<android.support.v4.view.ViewPager         android:id="@+id/viewPager"         android:layout_width="match_parent"         android:layout_height="130dp"         android:layout_alignParentBottom="true"         android:clipToPadding="false"         android:overScrollMode="never"         android:paddingEnd="80dp"         android:paddingLeft="80dp"         android:paddingRight="80dp"         android:paddingStart="80dp" /> 

then you will set the margin of the viewpager

int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10 * 2,             getResources().getDisplayMetrics());      viewPager.setPageMargin(-margin);     viewPager.setClipChildren(false); 

then you will set the adapter to the viewpager and its shadow transform which is responsible for the animation

pagerAdapter = new CardFragmentPagerAdapter(getSupportFragmentManager(),                                     dpToPixels(2, JobMapActivity.this),                                     titlesCard, catIconCard, catNameCard, startDateCard, startTimeCard);                             viewPager.setAdapter(pagerAdapter);                             viewPager.setOffscreenPageLimit(3);                             ShadowTransformer fragmentCardShadowTransformer = new ShadowTransformer(viewPager, pagerAdapter);                             fragmentCardShadowTransformer.enableScaling(true);                             viewPager.setPageTransformer(false, fragmentCardShadowTransformer); 

your CardFragmentPagerAdapter code is

import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v7.widget.CardView; import android.util.SparseArray; import android.view.ViewGroup;  import java.util.ArrayList; import java.util.List; public class CardFragmentPagerAdapter extends FragmentStatePagerAdapter implements CardAdapter {  private List<CardFragment> fragments; SparseArray<Fragment> registeredFragments = new SparseArray<>(); private float baseElevation; ArrayList<String> titles, icons, names, dates, times;  public CardFragmentPagerAdapter(FragmentManager fm, float baseElevation,                                 ArrayList<String> title, ArrayList<String> icon,                                 ArrayList<String> name, ArrayList<String> startDate,                                 ArrayList<String> startTime) {     super(fm);     fragments = new ArrayList<>();     this.baseElevation = baseElevation;     titles = title;     icons = icon;     names = name;     dates = startDate;     times = startTime;     for (int i = 0; i < titles.size(); i++) {         addCardFragment(new CardFragment());     } }  @Override public float getBaseElevation() {     return baseElevation; }  @Override public CardView getCardViewAt(int position) {     return fragments.get(position).getCardView(); }  @Override public int getCount() {     return fragments.size(); }  @Override public Fragment getItem(int position) {     return CardFragment.getInstance(position, titles.get(position),             icons.get(position), names.get(position), dates.get(position), times.get(position)); }  @Override public void destroyItem(ViewGroup container, int position, Object object) {     super.destroyItem(container, position, object);     registeredFragments.remove(position); }  public void addCardFragment(CardFragment fragment) {     fragments.add(fragment); }  @Override public Object instantiateItem(ViewGroup container, int position) {     Object fragment = super.instantiateItem(container, position);     Fragment fragment2 = (Fragment) super.instantiateItem(container, position);     fragments.set(position, (CardFragment) fragment);     registeredFragments.put(position, fragment2);     return fragment; }  public String getRegisteredFragment(int position) {     return fragments.get(position).getTitle(); }   @Override public int getItemPosition(Object object) {     return POSITION_NONE; } 

}

the cardAdapter is an interface for the elevation

    import android.support.v7.widget.CardView;  public interface CardAdapter {      int MAX_ELEVATION_FACTOR = 8;      float getBaseElevation();      CardView getCardViewAt(int position);      int getCount(); } 

your shadow transform class is

  import android.support.v4.view.ViewPager; import android.support.v7.widget.CardView; import android.view.View;  import com.foksart.greatskillsfixers.adapters.CardAdapter;  public class ShadowTransformer implements ViewPager.OnPageChangeListener, ViewPager.PageTransformer {      private ViewPager viewPager;     private CardAdapter cardAdapter;     private float lastOffset;     private boolean scalingEnabled;      public ShadowTransformer(ViewPager viewPager, CardAdapter adapter) {         this.viewPager = viewPager;         viewPager.addOnPageChangeListener(this);         cardAdapter = adapter;     }      public void enableScaling(boolean enable) {         if (scalingEnabled && !enable) {             // shrink main card             CardView currentCard = cardAdapter.getCardViewAt(viewPager.getCurrentItem());             if (currentCard != null) {                 currentCard.animate().scaleY(.9f); //                currentCard.animate().scaleX(.9f);             }         }else if(!scalingEnabled && enable){             // grow main card             CardView currentCard = cardAdapter.getCardViewAt(viewPager.getCurrentItem());             if (currentCard != null) {                 //enlarge the current item                 currentCard.animate().scaleY(1.3f); //                currentCard.animate().scaleX(1.3f);             }         }         scalingEnabled = enable;     }      @Override     public void transformPage(View page, float position) {      }      @Override     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {         int realCurrentPosition;         int nextPosition;         float baseElevation = cardAdapter.getBaseElevation();         float realOffset;         boolean goingLeft = lastOffset > positionOffset;          // If we're going backwards, onPageScrolled receives the last position         // instead of the current one         if (goingLeft) {             realCurrentPosition = position + 1;             nextPosition = position;             realOffset = 1 - positionOffset;         } else {             nextPosition = position + 1;             realCurrentPosition = position;             realOffset = positionOffset;         }          // Avoid crash on overscroll         if (nextPosition > cardAdapter.getCount() - 1                 || realCurrentPosition > cardAdapter.getCount() - 1) {             return;         }          CardView currentCard = cardAdapter.getCardViewAt(realCurrentPosition);          // This might be null if a fragment is being used         // and the views weren't created yet         if (currentCard != null) {             if (scalingEnabled) {                 currentCard.setScaleX((float) (1 + 0.1 * (1 - realOffset)));                 currentCard.setScaleY((float) (1 + 0.1 * (1 - realOffset)));             }             currentCard.setCardElevation((baseElevation + baseElevation                     * (CardAdapter.MAX_ELEVATION_FACTOR - 1) * (1 - realOffset)));         }          CardView nextCard = cardAdapter.getCardViewAt(nextPosition);          // We might be scrolling fast enough so that the next (or previous) card         // was already destroyed or a fragment might not have been created yet         if (nextCard != null) {             if (scalingEnabled) {                 nextCard.setScaleX((float) (1 + 0.1 * (realOffset)));                 nextCard.setScaleY((float) (1 + 0.1 * (realOffset)));             }             nextCard.setCardElevation((baseElevation + baseElevation                     * (CardAdapter.MAX_ELEVATION_FACTOR - 1) * (realOffset)));         }          lastOffset = positionOffset;     }      @Override     public void onPageSelected(int position) {      }      @Override     public void onPageScrollStateChanged(int state) {      } } 

the cardFragment for the layout

    import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.CardView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;  import com.bumptech.glide.Glide; import com.foksart.greatskillsfixers.ActivityClasses.JobMapActivity; import com.foksart.greatskillsfixers.R;   public class CardFragment extends Fragment {      private CardView cardView;     int position;     String title, icon, name, date, time;      public static Fragment getInstance(int position, String title,                                        String icon, String name,                                        String date, String time) {         CardFragment f = new CardFragment();         Bundle args = new Bundle();         args.putInt("position", position);         args.putString("title", title);         args.putString("icon", icon);         args.putString("name", name);         args.putString("date", date);         args.putString("time", time);          f.setArguments(args);         return f;     }      @Override     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,                              @Nullable Bundle savedInstanceState) {         View view = inflater.inflate(R.layout.card_map_item, container, false);         cardView = view.findViewById(R.id.cardView);         cardView.setMaxCardElevation(cardView.getCardElevation() * CardAdapter.MAX_ELEVATION_FACTOR);         TextView jobTitle = view.findViewById(R.id.jobTitle);         jobTitle.setText(title);          ImageView catIcon = view.findViewById(R.id.catIcon);         Glide.with(getActivity()).load(icon).into(catIcon);         catIcon.setColorFilter(Color.parseColor("#969798"));          TextView catName = view.findViewById(R.id.catName);         catName.setText(name);          TextView Date = view.findViewById(R.id.Date);         Date.setText(date);          TextView Time = view.findViewById(R.id.Time);         Time.setText(time);          view.setOnClickListener(new View.OnClickListener() {             @Override             public void onClick(View view) {                 ((JobMapActivity)getActivity()).viewPagerClick(position);             }         });          return view;     }       @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         position = getArguments().getInt("position");         title = getArguments().getString("title");         icon = getArguments().getString("icon");         name = getArguments().getString("name");         date = getArguments().getString("date");         time = getArguments().getString("time");     }      public CardView getCardView() {         return cardView;     }       public String getTitle(){return title;} 

Answers 3

Please Try to see if this helps.

public class MainActivity extends AppCompatActivity {   @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);      List<String>texts = new ArrayList<>();     texts.add("test 1");     texts.add("test 2");     texts.add("test 3");     texts.add("test 4");     texts.add("test 5");      LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);      RecyclerView myList = (RecyclerView) findViewById(R.id.RV);     myList.setLayoutManager(layoutManager);     myList.setAdapter(new TestAdapter(texts));  }    class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {      private List<String> TextsList;      public class MyViewHolder extends RecyclerView.ViewHolder {          public TextView title;           public MyViewHolder(View view) {              super(view);              title = (TextView) view.findViewById(R.id.title);          }      }        public class MyBigViewHolder extends RecyclerView.ViewHolder {          public TextView title;           public MyBigViewHolder(View view) {              super(view);              title = (TextView) view.findViewById(R.id.title);          }      }       public TestAdapter(List<String> textsList) {         this.TextsList = textsList;     }       @Override      public int getItemViewType(int position) {          // Just as an example, return 0 or 2 depending on position          // Note that unlike in ListView adapters, types don't have to be contiguous          return position % 2 * 3;      }      @Override     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         View itemView = null;             if(viewType == 0) {                 itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_row_2, parent, false);             }else{                 itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_list_row, parent, false);             }          return new MyViewHolder(itemView);     }      @Override     public void onBindViewHolder(MyViewHolder holder, int position) {         String text = TextsList.get(position);         holder.title.setText(text);     }      @Override     public int getItemCount() {         return TextsList.size();     } } 

}

Answers 4

Set a linearLayoutManager to get your recyclerView to work like horizontalScrollView.

Example here

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment