Reputation: 1551
I am trying to make simple card game where I need to show deck of cards laying on the desk horizontally and user can select any number of cards by clicking them. Ideally when use click on any card, card should elevate a bit from other cards. Plus cards are not completely visible, they are partially visible like this. I have created custom Recyclerview and used item decorator to change offset of cards. However whenever I change offset, first or last card of deck is completely overlapped by others. Like following image,
How to show above effect properly, without loosing first (or last) card? Also how to implement elevation of any of these cards when we click on them ? I tried to use "setElevation()" but it has no effect. It will be nice if I can achieve this without any third party library (however I am open to suggestions.). I used following code,
Game.java
public class Game extends AppCompatActivity {
private List<Card> cards = new ArrayList<>();
private RecyclerView.ItemDecoration decoration = new OverlapDecoration();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
RecyclerView marketDeck = (RecyclerView) findViewById(R.id.market_deck);
Card item1 = new Card();
item1.setImage(R.color.colorPrimary);
Card item2 = new Card();
item2.setImage(R.color.colorAccent);
cards.add(item1);
cards.add(item2);
cards.add(item1);
cards.add(item2);
cards.add(item1);
CardHolder cardHolder = new CardHolder(cards);
marketDeck.setAdapter(cardHolder);
marketDeck.setLayoutManager(new LinearLayoutManager(getBaseContext(), LinearLayoutManager.HORIZONTAL, false));
marketDeck.addItemDecoration(decoration);
cardHolder.setOnCardClick(new CardHolder.onCardClick() {
@Override
public void onClick(View v) {
v.setElevation(10);
}
});
}
private class OverlapDecoration extends RecyclerView.ItemDecoration {
//Following code from : http://stackoverflow.com/questions/27633454/how-to-overlap-items-in-linearlayoutmanager-recyclerview-like-stacking-cards
private final static int overlap = -100;
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
final int itemPosition = parent.getChildAdapterPosition(view);
if (itemPosition == RecyclerView.NO_POSITION) {
return;
}
outRect.set(overlap, 0, 0, 0);
}
}
}
CardHolder.java
public class CardHolder extends RecyclerView.Adapter<CardHolder.CardView> {
private List<Card> cards;
private onCardClick cardClick;
public CardHolder(List<Card> cards) {
this.cards = cards;
}
@Override
public CardView onCreateViewHolder(ViewGroup parent, int viewType) {
return new CardView(LayoutInflater.from(parent.getContext()).inflate(R.layout.card, parent, false));
}
@Override
public void onBindViewHolder(CardView holder, int position) {
Card card = cards.get(position);
holder.icon.setImageResource(card.getImage());
}
@Override
public int getItemCount() {
return cards.size();
}
class CardView extends RecyclerView.ViewHolder {
ImageView icon;
CardView(final View itemView) {
super(itemView);
icon = (ImageView) itemView.findViewById(R.id.card_icon);
icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cardClick.onClick(v);
}
});
}
}
void setOnCardClick(onCardClick click) {
cardClick = click;
}
public interface onCardClick {
void onClick(View v);
}
}
Card.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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5sp">
<ImageView
android:id="@+id/card_icon"
style="@style/CardTheme"
android:contentDescription="@null"
app:srcCompat="@color/colorPrimary" />
</LinearLayout>
game.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="com.company.someapp.Game">
<android.support.v7.widget.RecyclerView
android:id="@+id/market_deck"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Note: I have kept recyclerview width are "wrap_content" because number of cards will be variable.
Upvotes: 3
Views: 2848
Reputation: 1551
Got it working by adjusting margin of first element like following,
private class OverlapDecoration extends RecyclerView.ItemDecoration {
//Following code from : http://stackoverflow.com/questions/27633454/how-to-overlap-items-in-linearlayoutmanager-recyclerview-like-stacking-cards
private final static int overlap = -100;
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
final int itemPosition = parent.getChildAdapterPosition(view);
if (itemPosition == 0) {
outRect.set(0, 0, 0, 0);
} else {
outRect.set(overlap, 0, 0, 0);
}
}
}
Upvotes: 5