Reputation: 1031
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) :
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.
Upvotes: 6
Views: 2192
Reputation: 21
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();
}
}
}
Upvotes: 0
Reputation: 421
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;}
Upvotes: 1
Reputation: 11982
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:
Upvotes: 4