只在卡德维尔的顶端

我只想把一张卡片的顶部封死。

我使用下面的属性,它是圆角所有的角落。

我要展示所有牌的重叠部分

card_view:cardCornerRadius="4dp"

这是我的布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
card_view:cardCornerRadius="4dp"
card_view:cardPreventCornerOverlap="false"
>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/re1">


<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@color/colorAccent"
android:text="contact det"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:textSize="14dp"/>


<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/title"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>


<TextView
android:id="@+id/txtSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Surname"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/txtName"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
/>


<TextView
android:id="@+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textSize="10dp"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_marginRight="150dp"
android:layout_alignBaseline="@id/txtName"/>


<TextView
android:id="@+id/txtAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Address"
android:textSize="10dp"
android:layout_alignLeft="@id/txtEmail"
android:layout_alignBaseline="@id/txtSurname"/>


</RelativeLayout>




</android.support.v7.widget.CardView>
94886 次浏览

As per the question, I am assuming that you want to apply corner radius property to only top of the card. You can obtain this effect by using two CardView. Place one CardView inside another CardView and remove outer CardView corner radius property. Also apply a transparent background to your outer CardView Your inner CardView will have a cornerRadius value of 4dp. Then apply a marginTop to your inner CardView, so that its bottom part becomes hidden by the outer CardView. This way, the bottom corner radius of your inner CardView will be hidden.

You will have to put your xml content in your Inner CardView. Outer CardView serves only the purpose of hiding the bottom rounded corners of the inner CardView. Your xml layout will look like this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_outer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
card_view:cardBackgroundColor="@android:color/transparent"
card_view:cardCornerRadius="0dp"
card_view:cardElevation="4dp" >


<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="3dp"
card_view:cardElevation="0dp"
card_view:cardCornerRadius="4dp"
>


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="@+id/re1">


<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@color/colorAccent"
android:text="contact det"
android:gravity="center_vertical"
android:textColor="@android:color/white"
android:textSize="14dp"/>


<TextView
android:id="@+id/txtName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/title"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"/>


<TextView
android:id="@+id/txtSurname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Surname"
android:gravity="center_vertical"
android:textSize="10dp"
android:layout_below="@id/txtName"
android:layout_marginTop="10dp"
android:layout_marginLeft="5dp"
/>


<TextView
android:id="@+id/txtEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
android:textSize="10dp"
android:layout_marginTop="10dp"
android:layout_alignParentRight="true"
android:layout_marginRight="150dp"
android:layout_alignBaseline="@id/txtName"/>


<TextView
android:id="@+id/txtAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Address"
android:textSize="10dp"
android:layout_alignLeft="@id/txtEmail"
android:layout_alignBaseline="@id/txtSurname"/>


</RelativeLayout>




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

I have taken reference from this SO question: Question. I hope it solves your problem.

We can set the marginBottom of the card view in negative value.Margin should be same value as card radius. For Example,

    <FrameLayout
android:id="@+id/rootview"
android:layout_width="match_parent"
android:layout_height="match_parent">


<android.support.v7.widget.CardView
android:id="@+id/card_view"
android:layout_marginBottom="-3dp"
project:cardCornerRadius="3dp"
android:layout_width="match_parent"
android:layout_height="match_parent">


<!--The child view inside the cardview should have extra padding,so that negative margin will not affect the bottom padding of its child.Here normally we have 16dp bottom padding for child + margin bottom of the parent is 3dp=19dp comes.-->


<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="19dp"/>


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

It works for me.But I am in doubt whether it is the proper way of doing.Any suggestions are welcome.

I have been trying the same but none of the solutions provided worked for me.

The only thing that worked was:

1) Make a custom background resource (like a rectangle shape) with rounded corners.

2) set this custom background using the command -

cardView = view.findViewById(R.id.card_view2);
cardView.setBackgroundResource(R.drawable.card_view_bg);

Worked perfectly for me! Hope this helps you.

The XML layout I made with top left and bottom right radius.

<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:topLeftRadius="18dp" android:bottomRightRadius="18dp" />
</shape>

In your case, you need to change only topLeftRadius as well as topRightRadius.

Tricky thing because you can't make CardView do this. Internally it uses a RoundRectDrawable (package private) which uses roundRect like this:

 // rectf, rx, ry, paint
canvas.drawRoundRect(mBoundsF, mRadius, mRadius, paint);

Therefore you need a different solution, for example I found this gist by Ahmed-Abdelmeged where they use canvas clipping per each corner using a path to describe the outline.

So while I'm not the one who made this code, I'll post it here for future travellers.

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RoundedView">
<attr name="topLeftCornerRadius" format="dimension" />
<attr name="topRightCornerRadius" format="dimension" />
<attr name="bottomLeftCornerRadius" format="dimension" />
<attr name="bottomRightCornerRadius" format="dimension" />
</declare-styleable>
</resources>

and

package com.abdelmeged.ahmed.roundedlayout;


/**
* Created by ahmed on 9/17/2017.
*/


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;


/**
* Custom wrapper view to get round corner round view
*/
public class RoundedView extends FrameLayout {


/**
* The corners than can be changed
*/
private float topLeftCornerRadius;
private float topRightCornerRadius;
private float bottomLeftCornerRadius;
private float bottomRightCornerRadius;


public RoundedView(@NonNull Context context) {
super(context);
init(context, null, 0);
}


public RoundedView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}


public RoundedView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}


private void init(Context context, AttributeSet attrs, int defStyle) {
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.RoundedView, 0, 0);


//get the default value form the attrs
topLeftCornerRadius = typedArray.getDimension(R.styleable.
RoundedView_topLeftCornerRadius, 0);
topRightCornerRadius = typedArray.getDimension(R.styleable.
RoundedView_topRightCornerRadius, 0);
bottomLeftCornerRadius = typedArray.getDimension(R.styleable.
RoundedView_bottomLeftCornerRadius, 0);
bottomRightCornerRadius = typedArray.getDimension(R.styleable.
RoundedView_bottomRightCornerRadius, 0);


typedArray.recycle();
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}


@Override
protected void dispatchDraw(Canvas canvas) {
int count = canvas.save();


final Path path = new Path();


float[] cornerDimensions = {
topLeftCornerRadius, topLeftCornerRadius,
topRightCornerRadius, topRightCornerRadius,
bottomRightCornerRadius, bottomRightCornerRadius,
bottomLeftCornerRadius, bottomLeftCornerRadius};


path.addRoundRect(new RectF(0, 0, canvas.getWidth(), canvas.getHeight())
, cornerDimensions, Path.Direction.CW);


canvas.clipPath(path);


super.dispatchDraw(canvas);
canvas.restoreToCount(count);
}


public void setTopLeftCornerRadius(float topLeftCornerRadius) {
this.topLeftCornerRadius = topLeftCornerRadius;
invalidate();
}


public void setTopRightCornerRadius(float topRightCornerRadius) {
this.topRightCornerRadius = topRightCornerRadius;
invalidate();
}


public void setBottomLeftCornerRadius(float bottomLeftCornerRadius) {
this.bottomLeftCornerRadius = bottomLeftCornerRadius;
invalidate();
}


public void setBottomRightCornerRadius(float bottomRightCornerRadius) {
this.bottomRightCornerRadius = bottomRightCornerRadius;
invalidate();
}
}

This will let you clip the edge of images and views before they get rendered, therefore it does exactly what you want.

Well, I am so desperate finding a way to achieve this, one it's not possible, and creating your own shadow is somewhat I don't like the result and I lucky in my case I need it in the corner of the screen top right to be exact.

let's make it simple, make oversized card view into another view in my case I use frame layout then change it's x and y translation to what you need, well what I do is, make translation x and y into same exact card radius corner value. and there you go one sided rounded card view with barbaric way.

code ? sample ? here you go

<FrameLayout
android:id="@+id/miniTimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/frameLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">


<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:translationX="10dp"
android:translationY="-10dp"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="10dp"
app:cardUseCompatPadding="true">


<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/drwable_red__rounded_botleft_10"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="5dp"
android:paddingLeft="5dp"
android:paddingTop="10dp"
android:paddingEnd="10dp"
android:paddingRight="10dp"
android:paddingBottom="5dp">


<TextView
android:id="@+id/miniTimerText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorAccent"
android:textSize="12dp" />


</LinearLayout>
</androidx.cardview.widget.CardView>
</FrameLayout>

note : oh I dynamically generate the textview text so add it yourself :)

You can simply add an empty view to the bottom of your card view , set its background color the same as the cardView and also give a small negative margin to the top of the empty view, here is a sample :

<?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:id="@+id/linBottomSheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
>




<LinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
>


<androidx.cardview.widget.CardView


android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="-8dp"
android:elevation="2dp"
app:cardBackgroundColor="@color/colorAccent"
app:cardCornerRadius="10dp">








</androidx.cardview.widget.CardView>


</LinearLayout>


<View
        

android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_marginTop="-10dp"
android:background="@color/colorAccent" />
</LinearLayout>

I only created card view to wrap around image for corner radius then used constraint layout to add guidline and add below text layout to guidline. then guidline have overlapped on card with margin.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/card_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/_10sdp"
android:layout_marginRight="@dimen/_10sdp"
android:layout_marginTop="@dimen/_9sdp"
android:elevation="@dimen/_2sdp"
android:background="@drawable/card_top_corners"
android:clipChildren="true"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">




<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="@dimen/_152sdp"
app:cardCornerRadius="@dimen/_10sdp"
app:cardPreventCornerOverlap="false"
app:cardElevation="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">


<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="@dimen/_142sdp"
android:scaleType="centerCrop"
android:src="@drawable/shahruk"
android:visibility="visible" />




</androidx.cardview.widget.CardView>


<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline14"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="@dimen/_142sdp" />


<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"


app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline14">


<TextView
android:id="@+id/txt_title"
style="@style/medium_14sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="start"
android:paddingLeft="@dimen/_8sdp"
android:paddingTop="@dimen/_8sdp"
android:paddingRight="@dimen/_8sdp"
android:text="Rupa Singh: First indian woman to become a Jockey."
android:textColor="@color/city_news_text" />


<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/_8sdp"
android:layout_marginRight="@dimen/_8sdp"
android:orientation="horizontal">


<TextView
android:id="@+id/txt_date"
style="@style/medium_9sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxWidth="@dimen/_120sdp"
android:maxLines="1"
android:paddingTop="2dp"
android:text="Today"
android:textColor="@color/header_new"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />


<View
android:id="@+id/view2"
android:layout_width="1dp"
android:layout_height="@dimen/_8sdp"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/_7sdp"
android:layout_marginRight="@dimen/_7sdp"
android:background="@color/header_new"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/txt_date"
app:layout_constraintTop_toTopOf="parent" />


<TextView
android:id="@+id/txt_special_tag"
style="@style/medium_9sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="start|center_vertical"
android:maxLines="1"
android:paddingTop="2dp"
android:text="Top News"
android:textColor="@color/header_new"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/view2"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>


<TextView
style="@style/regular_11sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/_5sdp"
android:paddingLeft="@dimen/_8sdp"
android:paddingTop="@dimen/_2sdp"


android:paddingRight="@dimen/_8sdp"
android:paddingBottom="@dimen/_8sdp"
android:text="Napur records highest temperature in summers this year with  measure of 225 degree celsius....[Read more]"
android:textColor="@color/scheme_subtext" />
</LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

Please check result in image

In case if you just want to shape an image, use material ShapeableImageView that draws the bitmap with the provided Shape.

 <!-- Media -->
<com.google.android.material.imageview.ShapeableImageView
...
app:shapeAppearance="?attr/shapeAppearanceMediumComponent"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.Card.Media" />

In res/values/styles.xml:

<style name="ShapeAppearanceOverlay.App.Card.Media" parent="">
<item name="cornerSizeBottomLeft">0dp</item>
<item name="cornerSizeBottomRight">0dp</item>
<item name="cornerSizeTopLeft">8dp</item>
<item name="cornerSizeTopRight">8dp</item>
</style>

Or, you can use MaterialCardView

<com.google.android.material.card.MaterialCardView
style="@style/CustomCardViewStyle"
...>
</com.google.android.material.card.MaterialCardView>


<style name="CustomCardViewStyle" parent="@style/Widget.MaterialComponents.CardView">
<item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay_card_custom_corners</item>
</style>
    

    

<style name="ShapeAppearanceOverlay_card_custom_corners" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSizeTopRight">4dp</item>
<item name="cornerSizeTopLeft">8dp</item>
<item name="cornerSizeBottomRight">16dp</item>
<item name="cornerSizeBottomLeft">0dp</item>
</style>

You cand find a good answer here

My custom way to implemented with a lib

//Rounded card

add this implementation on build.gradle

implementation 'com.github.captain-miao:optroundcardview:1.0.0'

in XML:

<com.github.captain_miao.optroundcardview.OptRoundCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
app:optRoundCardCornerRadius="40dp"
app:optRoundCardLeftBottomCorner="false"
app:optRoundCardRightBottomCorner="false"
app:optRoundCardBackgroundColor="#E2EAF8">

Simply scrolling the CardView on the Y-axis did the trick for me. Note the scrollY attribute on the CardView

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="0dp"
app:cardCornerRadius="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:scrollY="10dp"
>


<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="80dp"
android:scaleType="fitXY"
android:src="@drawable/sample_post_image"
/>


</androidx.cardview.widget.CardView>

I tried this answer but the cut-out radius has some dark background, which is not desirable.

Use this library https://github.com/captain-miao/OptionRoundCardview

Instead of using CardView, use OptRoundCardView

It's better to update your CardView form:

androidx.cardview.widget.CardView

to new one:

com.google.android.material.card.MaterialCardView

like this:

<com.google.android.material.card.MaterialCardView
android:id="@+id/bottomCard"
android:layout_width="70dp"
android:layout_height="70dp">

then in Kotlin use like this:

 var shapeAppearanceModel: ShapeAppearanceModel.Builder =ShapeAppearanceModel().toBuilder()
shapeAppearanceModel.setBottomRightCorner(
CornerFamily.ROUNDED,
CornerSize { return@CornerSize 45F })
binding.bottomCard.shapeAppearanceModel =shapeAppearanceModel.build()

instead of binding you can put

bottomCard=view.findViewById<MaterialCardView>(R.id.bottomCard)