silvio.pereira
silvio.pereira

Reputation: 538

How to create custom CardView with internal FrameLayout on Android

I was in need of adding a border to a CardView and the way I found to do that (here in stackoverflow) was creating a FrameLayout inside and add a shape background to it. This approach worked nicely but now I need to extend this to a custom layout to avoid duplicating this code every time I want to use this cardviewWithBorders!

The current code looks like this:

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:elevation="4dp"
        app:cardCornerRadius="4dp"
        app:cardUseCompatPadding="true">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/shape_border_corner_radius"
            android:padding="16dp">

            <EditText
                android:id="@+id/fieldInput"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/transparent"
                android:lineSpacingMultiplier="1.5"
                android:textAppearance="@style/LatoRegular"
                android:textSize="16sp"
                tools:hint="Type in your E-mail" />
        </FrameLayout>
    </android.support.v7.widget.CardView>

All I want is to have a component of the CardView and the FrameLayout which I could use like this:

<com.example.BorderCardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <content goes here />

</com.example.BorderCardView>

What can I do to achieve this behavior?

Upvotes: 1

Views: 2161

Answers (1)

Ben P.
Ben P.

Reputation: 54204

You're in luck that your "inner" view is a FrameLayout and that CardView extends FrameLayout, since this means that you don't need to worry about the exact type of your child views' LayoutParams objects.

public class BorderCardView extends CardView {

    public BorderCardView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        FrameLayout.LayoutParams params = 
                new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);

        FrameLayout frame = new FrameLayout(getContext());
        frame.setLayoutParams(params);
        frame.setBackground(/* your background drawable */);
        frame.setPadding(/* your left/top/right/bottom padding */);

        while (getChildCount() > 0) {
            View child = getChildAt(0);

            FrameLayout.LayoutParams childParams =
                    (FrameLayout.LayoutParams) child.getLayoutParams();

            removeView(child);
            frame.addView(child);

            child.setLayoutParams(childParams);
        }

        addView(frame);
    }
}

What you're doing here is dynamically creating your "inner" FrameLayout, and then looping over all children from your layout, removing them from the CardView and adding them to the FrameLayout instead, and then finally adding the "inner" frame to the CardView.

Upvotes: 3

Related Questions