Unable to get exact circle shape when using card v

2020-02-20 07:04发布

问题:

I'm using card view for floating action button in android material design. I'm using following code for get the circle

<android.support.v7.widget.CardView
    android:id="@+id/fab"
    android:layout_width="38dp"
    android:layout_height="38dp"
    android:layout_marginBottom="10dp"
    android:layout_marginRight="10dp"
    card_view:background="@color/blue"
    card_view:cardCornerRadius="19dp"
    card_view:cardPreventCornerOverlap = "false"
    card_view:cardElevation="6dp" >
</android.support.v7.widget.CardView>

I have set corner radius as half of width. but still I can't get the circle shape.

回答1:

I have solved the problem. Now android providing design library for material design, which has the FloatingActionButton. No need of customizing card view for floating action button.

<android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"  />

Add design library in gradle dependencies

compile 'com.android.support:design:23.1.1'

For more detail refer this link



回答2:

To get a perfect circle shape using a card view, corner radius should be 1/2 of width or height (taking into consideration that it is a square). also, I have noticed that you are using card_view params, don't.

<android.support.v7.widget.CardView
android:layout_width="38dp"
android:layout_height="38dp"
app:cardCornerRadius="19dp"
app:cardElevation="6dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:id="@+id/fab"
android:background="@color/blue"
>



回答3:

To achieve a circular shape using Card view you can set the shape property, android:shape="ring".
app:cardCornerRadius should be set to half the width or height of the child view

<android.support.v7.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:innerRadius="0dp"
        android:shape="ring"
        app:cardCornerRadius="75dp">

        <ImageView
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_gravity="center"
            android:background="@drawable/image" />
     </android.support.v7.widget.CardView>


回答4:

use

shape = "ring"

use same layout_height and layout_weight

and

app:cardCornerRadius= half of layout_height or layout_weight

example

<android.support.v7.widget.CardView
                        android:id="@+id/cardview"
                        android:layout_width="110dp"
                        android:layout_height="110dp"
                        android:shape="ring"
                        app:cardCornerRadius="55dp">
</android.support.v7.widget.CardView>


回答5:

I came up with simple Solution of Using a Drawable and it looks amazing!

Get Drawable here https://drive.google.com/open?id=0B4Vo_ku-aIKzUFFnUjYxYVRLaGc



回答6:

I tried your code and found out that the Cards were less round with respect to the increase in the card elevation value.Try setting it to zero and this at least makes it look better.

card_view:cardElevation="0dp";

But a probably better option would be to use the FloatingActionButton for the round button

<android.support.design.widget.FloatingActionButton
    android:src="@drawable/your_drawble_name"
    app:fabSize="normal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />


回答7:

Yes, I have achieved it by reducing half of the CardCornerRadius to its View's Height.



回答8:

first import the drawbleToolBox library in your project. with this library, you can create drawable dynamically.

for make your cardview circle your radius must be half of its height/widht.

                int radius = cardView.getHeight()/2;
                Drawable drawable = new DrawableBuilder()
                    .rectangle()
                    .solidColor(0xffffffff)

                    .topRightRadius(radius) // in pixels
                    .bottomRightRadius(radius)
                     //otherplaces
                    .build();



                holder.cardView.setBackground(drawable);

if you are using cardview in your recycleview, getting the cardview widths doesn't work becuse it doesn't create yet. so you should do as below

holder.cardView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
    {
        @Override
        public boolean onPreDraw()
        {
         //codes here.
        }
     }


回答9:

card_layout.xml

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="250dp"
    android:layout_height="200dp">

    <ImageView
        android:id="@+id/card_thumbnail_image"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        style="@style/card_thumbnail_image"/>
</android.support.v7.widget.CardView>

MainActivity.java

 ImageView imageView = (ImageView) findViewById(R.id.card_thumbnail_image);
    Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rose);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
        //Default 
        imageView.setBackgroundResource(R.drawable.rose);
    } else {
        //RoundCorners 
        RoundCornersDrawable round = new RoundCornersDrawable(mBitmap,
                getResources().getDimension(R.dimen.cardview_default_radius), 0); //or your custom radius

        CardView cardView = (CardView) findViewById(R.id.card_view);
        cardView.setPreventCornerOverlap(false); //it is very important

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            imageView.setBackground(round);
        else
            imageView.setBackgroundDrawable(round);
    }

RoundCornersDrawable.java

    public class RoundCornersDrawable extends Drawable {

    private final float mCornerRadius;
    private final RectF mRect = new RectF();
    //private final RectF mRectBottomR = new RectF();
    //private final RectF mRectBottomL = new RectF();
    private final BitmapShader mBitmapShader;
    private final Paint mPaint;
    private final int mMargin;

    public RoundCornersDrawable(Bitmap bitmap, float cornerRadius, int margin) {
        mCornerRadius = cornerRadius;

        mBitmapShader = new BitmapShader(bitmap,
                Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setShader(mBitmapShader);

        mMargin = margin;
    }

    @Override
    protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);
        //mRectBottomR.set( (bounds.width() -mMargin) / 2, (bounds.height() -mMargin)/ 2,bounds.width() - mMargin, bounds.height() - mMargin);
       // mRectBottomL.set( 0,  (bounds.height() -mMargin) / 2, (bounds.width() -mMargin)/ 2, bounds.height() - mMargin);
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.drawRoundRect(mRect, mCornerRadius, mCornerRadius, mPaint);
        //canvas.drawRect(mRectBottomR, mPaint); //only bottom-right corner not rounded
        //canvas.drawRect(mRectBottomL, mPaint); //only bottom-left corner not rounded

    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
        mPaint.setColorFilter(cf);
    }


}


回答10:

<androidx.cardview.widget.CardView
        android:layout_width="60dp"
        android:layout_marginStart="150dp"
        app:cardCornerRadius="360dp"
        android:layout_height="60dp">