yuyakaido / CardStackView

📱Tinder like swipeable card view for Android
Apache License 2.0
2.37k stars 448 forks source link

Set card height to wrap_content #236

Closed P1NG2WIN closed 5 years ago

P1NG2WIN commented 5 years ago

How i can set card height to wrap_content? Now, even if card height set to wrap content, the card is stretched to the entire CardStackView.

image

SOLUTION:

The solution is to add a card-view to FrameLayout or another parent layout. Here is an example.

<FrameLayout 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="wrap_content"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardCornerRadius="8dp"
        app:cardElevation="5dp"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="true"
        android:layout_gravity="center">

        <!--change layout_gravity of card view if you want different position in card stack-->

        <ImageView
            android:id="@+id/front_img"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            tools:srcCompat="@drawable/cat" />

    </androidx.cardview.widget.CardView>

</FrameLayout>

Card layout file:

<android.support.v7.widget.CardView 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/cardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
app:cardCornerRadius="8dp"
app:cardElevation="5dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">`

<ImageView
    android:id="@+id/front_img"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:adjustViewBounds="true"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:srcCompat="@drawable/cat" />

</android.support.v7.widget.CardView>

Main layout file:

<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=".TestActivity">

<com.yuyakaido.android.cardstackview.CardStackView
    android:id="@+id/container"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:clipToPadding="false"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

</com.yuyakaido.android.cardstackview.CardStackView>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/btn_play"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginBottom="8dp"
    android:clickable="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:srcCompat="@drawable/ic_play_black_24dp" />

</android.support.constraint.ConstraintLayout>

gaborbiro commented 5 years ago

Would love to know the answer to this one

gaborbiro commented 5 years ago

Hey @P1NG2WIN, thanks for replying.

In my case it is happening with any drawable and even your sample app.

Here's what I'd like to achieve: The images I'm using are a lot shorter than the screen height and I would like the CardView's to vertically wrap around the image, whatever the image height might be. The way I'm trying to do it is by setting layout_height of both the CardStackView and my CardView layouts to "wrap_content". In my case though, the result is that the whole CardStackView disappears (checked it with "Show layout bounds" setting, everything is gone). Here's my code:

The activity:

<?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:clipChildren="false"
    android:layout_height="match_parent"
    android:layout_width="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:clipChildren="false"
        android:id="@+id/fab_container"
        android:layout_height="wrap_content"
        android:layout_width="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:backgroundTint="@color/destructive_red"
            android:clipChildren="false"
            android:id="@+id/fab_skip"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/margin"
            android:layout_width="wrap_content"
            android:src="@drawable/skip_red_24dp"
            android:tint="#FFF"
            app:borderWidth="0dp"
            app:fabSize="normal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/fab_like"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:backgroundTint="@color/primaryColor"
            android:id="@+id/fab_like"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/margin"
            android:layout_width="wrap_content"
            android:src="@drawable/like_green_24dp"
            android:tint="#FFF"
            app:borderWidth="0dp"
            app:fabSize="normal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/fab_skip" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.yuyakaido.android.cardstackview.CardStackView
        android:clipChildren="false"
        android:id="@+id/card_stack_view"
        android:layout_height="0dp"
        android:layout_marginBottom="@dimen/half_margin"
        android:layout_marginEnd="@dimen/half_margin"
        android:layout_marginStart="@dimen/half_margin"
        android:layout_width="0dp"
        tools:listitem="@layout/card_advertisement"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/fab_container"/>
</androidx.constraintlayout.widget.ConstraintLayout>

And the card view:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/half_margin"
    android:layout_width="match_parent"
    app:cardBackgroundColor="@android:color/white"
    app:cardCornerRadius="@dimen/card_corner_radius"
    app:cardElevation="@dimen/card_elevation"
    app:cardPreventCornerOverlap="true">

    <ImageView
        android:adjustViewBounds="true"
        android:id="@+id/image"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:src="@drawable/logo"/>
</androidx.cardview.widget.CardView>

As you can see both the CardView and the ImageView inside it is set to "wrap_content". In the CardStackView I tried setting the height to "wrap_content" but the whole stack disappeared. If I use "0dp", it looks like this (too tall): Screenshot_20190417-215012

I'd greatly appreciate any hint of what I'm doing wrong and thank you for maintaining this library, it's awesome.

P1NG2WIN commented 5 years ago

As you can see both the CardView and the ImageView inside it is set to "wrap_content". In the CardStackView I tried setting the height to "wrap_content" but the whole stack disappeared. If I use "0dp", it looks like this (too tall): Screenshot_20190417-215012

First of all, never use the nested Constraint Layout in Constraint Layout because it hurts performance a lot. Constraint Layout was designed to have as little sub view as possible. Something like this: `

    `<androidx.constraintlayout.widget.ConstraintLayout`  
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     xmlns:tools="http://schemas.android.com/tools">

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab_skip"
    android:layout_width="52dp"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/green"
    android:clipChildren="false"
    android:src="@drawable/ic_next_black_24dp"
    android:tint="#FFF"
    app:borderWidth="0dp"

    android:layout_margin="8dp"

    app:fabSize="normal"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/fab_like" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab_like"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/green"
    android:src="@drawable/ic_previous_black_24dp"

    android:tint="#FFF"
    app:borderWidth="0dp"
    app:fabSize="normal"

    app:layout_constraintBottom_toBottomOf="@+id/fab_skip"
    app:layout_constraintEnd_toStartOf="@+id/fab_skip"
    app:layout_constraintStart_toStartOf="parent" />

<com.yuyakaido.android.cardstackview.CardStackView
    android:clipChildren="false"
    android:id="@+id/card_stack_view"
    android:layout_height="0dp"
    android:layout_width="0dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>`

Next, try to change android:src="@drawable/logo" to tools:srcCompat="@drawable/logo" And which library for downloading images do you use?

gaborbiro commented 5 years ago

I use Glide

P1NG2WIN commented 5 years ago

Can you share code?

P1NG2WIN commented 5 years ago

Also try to remove setBackground color from card view layout

gaborbiro commented 5 years ago

Tried removing the background color, nothing changed.

This is my adapter:

class CardStackAdapter(
    var advertisements: List<AdvertisementCard> = emptyList()
) : RecyclerView.Adapter<CardStackAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return android.view.LayoutInflater.from(parent.context).run {
            ViewHolder(inflate(R.layout.card_advertisement, parent, false))
        }
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val advertisement = advertisements[position]
        Glide.with(holder.itemView.context)
            .load(advertisement.imageUri)
            .into(holder.image)
    }

    override fun getItemCount(): Int {
        return advertisements.size
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var image: ImageView = view.image
    }
}

This is how the app looks when I use real images and "0dp" for layout_height in the CardStackView: screen-recording_20190418-093040

Which is expected. But when I set it to "wrap_content", the screen is empty (except the floating action buttons).

gaborbiro commented 5 years ago

Note: About the embedded ConstraintLayouts, I totally agree that the hierarchy is not as flat as it could be. Unfortunately I was forced to do it this way. If I flatten out the hierarchy the way you suggested, the cards are rendered beneath the floating action buttons (which is not what I want). Like this: screen-recording_20190418-100009

But with my implementation they go over the fabs nicely.

P1NG2WIN commented 5 years ago

Also try to set bottom constraint of card stack to the top of fab. It should be the same result

P1NG2WIN commented 5 years ago

Which is expected. But when I set it to "wrap_content", the screen is empty (except the floating action buttons).

The solution is to add a card-view to FrameLayout or another parent layout. Here is an example.

`

<FrameLayout 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="wrap_content"
    xmlns:tools="http://schemas.android.com/tools">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardCornerRadius="8dp"
        app:cardElevation="5dp"
        app:cardPreventCornerOverlap="false"
        app:cardUseCompatPadding="true"
        android:layout_gravity="center">

        <!--change layout_gravity of card view if you want different position in card stack-->

        <ImageView
            android:id="@+id/front_img"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            tools:srcCompat="@drawable/cat" />

    </androidx.cardview.widget.CardView>

</FrameLayout>`
Jigar-zest commented 1 year ago

@gaborbiro Did you find the solution for this?