【问题标题】:ImageView with only one rounded cornerImageView 只有一个圆角
【发布时间】:2020-04-02 13:22:27
【问题描述】:

我正在尝试制作ImageView 的一个圆角,如下图所示,但带有右下角。尝试使用背景形状,但它根本不起作用。 Glide 加载的所有图像。我应该使用ViewOutlineProvider 之类的东西吗?有没有一种有效的方法来做到这一点?谢谢!

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <corners
        android:radius="2dp"
        android:bottomRightRadius="20dp"
        android:bottomLeftRadius="0dp"
        android:topLeftRadius="0dp"
        android:topRightRadius="0dp"/>
</shape>

【问题讨论】:

  • 这里是可能对你有用的库:github.com/pungrue26/SelectableRoundedImageView
  • 你能发布一张视图的图片吗,它是如何使用你添加的当前代码寻找你的?因为相同的代码给了我你想要的底部圆角。还要发布要应用形状的 ImageView 的代码

标签: android material-components material-components-android android-shape android-shapedrawable


【解决方案1】:

Material Components library1.2.0-alpha03版本开始引入了ShapeableImageView

只需使用类似的东西:

  <com.google.android.material.imageview.ShapeableImageView
      android:id="@+id/image_view"
      android:scaleType="centerInside"
      android:adjustViewBounds="true"
      ../>

然后在您的代码中,您可以将ShapeAppearanceModel 应用于:

ShapeableImageView imageView = findViewById(R.id.image_view);
float radius = getResources().getDimension(R.dimen.default_corner_radius);
imageView.setShapeAppearanceModel(imageView.getShapeAppearanceModel()
    .toBuilder()
    .setTopRightCorner(CornerFamily.ROUNDED,radius)
    .build());

你也可以在xml中应用shapeAppearanceOverlay参数:

<com.google.android.material.imageview.ShapeableImageView
      app:shapeAppearanceOverlay="@style/customRroundedImageView"
      app:srcCompat="@drawable/ic_image" />

与:

  <style name="customRoundedImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">0dp</item>   
    <item name="cornerSizeTopRight">8dp</item>
  </style>

使用 jetpack compose,您可以使用 RoundedCornerShape 应用 clip 修饰符:

Image(painterResource(id = R.drawable.xxx),
    contentDescription = "xxxx",
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(xx.dp,xx.dp)
        .clip(RoundedCornerShape(topStart = 12.dp)),
)

【讨论】:

  • 是否仍然不支持在ShapeableImageView 上通过 XML(直接在视图上或通过样式/主题)自定义 shapeAppearance 和/或 shapeAppearanceOverlay
  • @Richard 是的。例如,您可以在 xml 布局中使用:app:shapeAppearance="?attr/shapeAppearanceMediumComponent"
  • 谢谢,它成功了 ;-) 虽然它在 Android Studio 布局预览中没有正确显示。运行时,ShapeableImageView 正确显示(带有圆形边缘)。在预览时,它显示一个矩形。这是一个错误吗?
  • 此功能现在在 1.2.0 中稳定
【解决方案2】:

此外,如果您想摆脱在“.java”文件中编写代码。然后你可以像下面这样定义 style 并将其添加到你的ShapeableImageView:

<com.google.android.material.imageview.ShapeableImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ex_image"
    app:shapeAppearanceOverlay="@style/roundedImageView"
    />

然后:

<style name="roundedImageView" parent="">
    <item name="cornerFamilyTopRight">rounded</item>
    <item name="cornerSizeTopRight">30dp</item>
</style>

【讨论】:

    【解决方案3】:

    这是您的主要布局文件,它使用自定义可绘制“round_one.xml”文件。只需复制并粘贴此代码。 它有望满足您的要求。

    <?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"
        xmlns:tools="http://schemas.android.com/tools"
        android:elevation="@dimen/_10sdp"
        android:background="@color/white"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/round_one"
            android:orientation="vertical"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="@dimen/_80sdp"
                android:layout_gravity="center"
                android:scaleType="fitXY"
                android:src="@android:drawable/ic_menu_day" />
            <TextView
                android:id="@+id/textView22"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="8dp"
                android:text="title goes here" />
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="8dp"
                android:layout_marginBottom="8dp"
                android:text="Secondary text"
                />
        </LinearLayout>
    
    
    </androidx.cardview.widget.CardView>
    

    round_one.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android">
        <solid android:color="@color/gray" />
        <corners android:topRightRadius="50dp" />
    </shape>
    

    【讨论】:

      【解决方案4】:

      要只圆 imageview 的一个角,请按照以下步骤和代码:

      将以下文件添加到您的项目RoundCornerImageView.java

      package com.skd.stackdemo;
      
      import android.annotation.SuppressLint;
      import android.content.Context;
      import android.content.res.ColorStateList;
      import android.content.res.Resources;
      import android.content.res.TypedArray;
      import android.graphics.Bitmap;
      import android.graphics.BitmapShader;
      import android.graphics.Canvas;
      import android.graphics.Color;
      import android.graphics.ColorFilter;
      import android.graphics.Matrix;
      import android.graphics.Paint;
      import android.graphics.Path;
      import android.graphics.PixelFormat;
      import android.graphics.Rect;
      import android.graphics.RectF;
      import android.graphics.Shader;
      import android.graphics.drawable.BitmapDrawable;
      import android.graphics.drawable.Drawable;
      import android.graphics.drawable.LayerDrawable;
      import android.net.Uri;
      import android.util.AttributeSet;
      import android.util.Log;
      import android.widget.ImageView;
      
      public class RoundCornerImageView extends ImageView {
      
          public static final String TAG = "RoundCornerImageView";
      
          private int mResource = 0;
      
          private static final ScaleType[] sScaleTypeArray = {
                  ScaleType.MATRIX,
                  ScaleType.FIT_XY,
                  ScaleType.FIT_START,
                  ScaleType.FIT_CENTER,
                  ScaleType.FIT_END,
                  ScaleType.CENTER,
                  ScaleType.CENTER_CROP,
                  ScaleType.CENTER_INSIDE
          };
      
          // Set default scale type to FIT_CENTER, which is default scale type of
          // original ImageView.
          private ScaleType mScaleType = ScaleType.FIT_CENTER;
      
          private float mLeftTopCornerRadius = 0.0f;
          private float mRightTopCornerRadius = 0.0f;
          private float mLeftBottomCornerRadius = 0.0f;
          private float mRightBottomCornerRadius = 0.0f;
      
          private float mBorderWidth = 0.0f;
          private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
          private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
      
          private boolean isOval = false;
      
          private Drawable mDrawable;
      
          private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
      
          public RoundCornerImageView(Context context) {
              super(context);
          }
      
          public RoundCornerImageView(Context context, AttributeSet attrs) {
              this(context, attrs, 0);
          }
      
          public RoundCornerImageView(Context context, AttributeSet attrs, int defStyle) {
              super(context, attrs, defStyle);
      
              TypedArray a = context.obtainStyledAttributes(attrs,
                      R.styleable.SelectableRoundedImageView, defStyle, 0);
      
              final int index = a.getInt(R.styleable.SelectableRoundedImageView_android_scaleType, -1);
              if (index >= 0) {
                  setScaleType(sScaleTypeArray[index]);
              }
      
              mLeftTopCornerRadius = a.getDimensionPixelSize(
                      R.styleable.SelectableRoundedImageView_sriv_left_top_corner_radius, 0);
              mRightTopCornerRadius = a.getDimensionPixelSize(
                      R.styleable.SelectableRoundedImageView_sriv_right_top_corner_radius, 0);
              mLeftBottomCornerRadius = a.getDimensionPixelSize(
                      R.styleable.SelectableRoundedImageView_sriv_left_bottom_corner_radius, 0);
              mRightBottomCornerRadius = a.getDimensionPixelSize(
                      R.styleable.SelectableRoundedImageView_sriv_right_bottom_corner_radius, 0);
      
              if (mLeftTopCornerRadius < 0.0f || mRightTopCornerRadius < 0.0f
                      || mLeftBottomCornerRadius < 0.0f || mRightBottomCornerRadius < 0.0f) {
                  throw new IllegalArgumentException("radius values cannot be negative.");
              }
      
              mRadii = new float[] {
                      mLeftTopCornerRadius, mLeftTopCornerRadius,
                      mRightTopCornerRadius, mRightTopCornerRadius,
                      mRightBottomCornerRadius, mRightBottomCornerRadius,
                      mLeftBottomCornerRadius, mLeftBottomCornerRadius };
      
              mBorderWidth = a.getDimensionPixelSize(
                      R.styleable.SelectableRoundedImageView_sriv_border_width, 0);
              if (mBorderWidth < 0) {
                  throw new IllegalArgumentException("border width cannot be negative.");
              }
      
              mBorderColor = a
                      .getColorStateList(R.styleable.SelectableRoundedImageView_sriv_border_color);
              if (mBorderColor == null) {
                  mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
              }
      
              isOval = a.getBoolean(R.styleable.SelectableRoundedImageView_sriv_oval, false);
              a.recycle();
      
              updateDrawable();
          }
      
          @Override
          protected void drawableStateChanged() {
              super.drawableStateChanged();
              invalidate();
          }
      
          @Override
          public ScaleType getScaleType() {
              return mScaleType;
          }
      
          @Override
          public void setScaleType(ScaleType scaleType) {
              super.setScaleType(scaleType);
              mScaleType = scaleType;
              updateDrawable();
          }
      
          @Override
          public void setImageDrawable(Drawable drawable) {
              mResource = 0;
              mDrawable = RoundCornerDrawable.fromDrawable(drawable, getResources());
              super.setImageDrawable(mDrawable);
              updateDrawable();
          }
      
          @Override
          public void setImageBitmap(Bitmap bm) {
              mResource = 0;
              mDrawable = RoundCornerDrawable.fromBitmap(bm, getResources());
              super.setImageDrawable(mDrawable);
              updateDrawable();
          }
      
          @Override
          public void setImageResource(int resId) {
              if (mResource != resId) {
                  mResource = resId;
                  mDrawable = resolveResource();
                  super.setImageDrawable(mDrawable);
                  updateDrawable();
              }
          }
      
          @Override
          public void setImageURI(Uri uri) {
              super.setImageURI(uri);
              setImageDrawable(getDrawable());
          }
      
          private Drawable resolveResource() {
              Resources rsrc = getResources();
              if (rsrc == null) {
                  return null;
              }
      
              Drawable d = null;
      
              if (mResource != 0) {
                  try {
                      d = rsrc.getDrawable(mResource);
                  } catch (Resources.NotFoundException e) {
                      Log.w(TAG, "Unable to find resource: " + mResource, e);
                      // Don't try again.
                      mResource = 0;
                  }
              }
              return RoundCornerDrawable.fromDrawable(d, getResources());
          }
      
          private void updateDrawable() {
              if (mDrawable == null) {
                  return;
              }
      
              ((RoundCornerDrawable) mDrawable).setScaleType(mScaleType);
              ((RoundCornerDrawable) mDrawable).setCornerRadii(mRadii);
              ((RoundCornerDrawable) mDrawable).setBorderWidth(mBorderWidth);
              ((RoundCornerDrawable) mDrawable).setBorderColor(mBorderColor);
              ((RoundCornerDrawable) mDrawable).setOval(isOval);
          }
      
          public float getCornerRadius() {
              return mLeftTopCornerRadius;
          }
      
          /**
           * Set radii for each corner.
           *
           * @param leftTop The desired radius for left-top corner in dip.
           * @param rightTop The desired desired radius for right-top corner in dip.
           * @param leftBottom The desired radius for left-bottom corner in dip.
           * @param rightBottom The desired radius for right-bottom corner in dip.
           *
           */
          public void setCornerRadiiDP(float leftTop, float rightTop, float leftBottom, float rightBottom) {
              final float density = getResources().getDisplayMetrics().density;
      
              final float lt = leftTop * density;
              final float rt = rightTop * density;
              final float lb = leftBottom * density;
              final float rb = rightBottom * density;
      
              mRadii = new float[] { lt, lt, rt, rt, rb, rb, lb, lb };
              updateDrawable();
          }
      
          public float getBorderWidth() {
              return mBorderWidth;
          }
      
          /**
           * Set border width.
           *
           * @param width
           *            The desired width in dip.
           */
          public void setBorderWidthDP(float width) {
              float scaledWidth = getResources().getDisplayMetrics().density * width;
              if (mBorderWidth == scaledWidth) {
                  return;
              }
      
              mBorderWidth = scaledWidth;
              updateDrawable();
              invalidate();
          }
      
          public int getBorderColor() {
              return mBorderColor.getDefaultColor();
          }
      
          public void setBorderColor(int color) {
              setBorderColor(ColorStateList.valueOf(color));
          }
      
          public ColorStateList getBorderColors() {
              return mBorderColor;
          }
      
          public void setBorderColor(ColorStateList colors) {
              if (mBorderColor.equals(colors)) {
                  return;
              }
      
              mBorderColor = (colors != null) ? colors : ColorStateList
                      .valueOf(DEFAULT_BORDER_COLOR);
              updateDrawable();
              if (mBorderWidth > 0) {
                  invalidate();
              }
          }
      
          public boolean isOval() {
              return isOval;
          }
      
          public void setOval(boolean oval) {
              isOval = oval;
              updateDrawable();
              invalidate();
          }
      
          static class RoundCornerDrawable extends Drawable {
      
              private static final String TAG = "RoundCornerDrawable";
              private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
      
              private RectF mBounds = new RectF();
              private RectF mBorderBounds = new RectF();
      
              private final RectF mBitmapRect = new RectF();
              private final int mBitmapWidth;
              private final int mBitmapHeight;
      
              private final Paint mBitmapPaint;
              private final Paint mBorderPaint;
      
              private BitmapShader mBitmapShader;
      
              private float[] mRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
              private float[] mBorderRadii = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 };
      
              private boolean mOval = false;
      
              private float mBorderWidth = 0;
              private ColorStateList mBorderColor = ColorStateList.valueOf(DEFAULT_BORDER_COLOR);
              // Set default scale type to FIT_CENTER, which is default scale type of
              // original ImageView.
              private ScaleType mScaleType = ScaleType.FIT_CENTER;
      
              private Path mPath = new Path();
              private Bitmap mBitmap;
              private boolean mBoundsConfigured = false;
      
              public RoundCornerDrawable(Bitmap bitmap, Resources r) {
                  mBitmap = bitmap;
                  mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
      
                  if (bitmap != null) {
                      mBitmapWidth = bitmap.getScaledWidth(r.getDisplayMetrics());
                      mBitmapHeight = bitmap.getScaledHeight(r.getDisplayMetrics());
                  } else {
                      mBitmapWidth = mBitmapHeight = -1;
                  }
      
                  mBitmapRect.set(0, 0, mBitmapWidth, mBitmapHeight);
      
                  mBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                  mBitmapPaint.setStyle(Paint.Style.FILL);
                  mBitmapPaint.setShader(mBitmapShader);
      
                  mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                  mBorderPaint.setStyle(Paint.Style.STROKE);
                  mBorderPaint.setColor(mBorderColor.getColorForState(getState(), DEFAULT_BORDER_COLOR));
                  mBorderPaint.setStrokeWidth(mBorderWidth);
              }
      
              public static RoundCornerDrawable fromBitmap(Bitmap bitmap, Resources r) {
                  if (bitmap != null) {
                      return new RoundCornerDrawable(bitmap, r);
                  } else {
                      return null;
                  }
              }
      
              @SuppressLint("LongLogTag")
              public static Drawable fromDrawable(Drawable drawable, Resources r) {
                  if (drawable != null) {
                      if (drawable instanceof RoundCornerDrawable) {
                          return drawable;
                      } else if (drawable instanceof LayerDrawable) {
                          LayerDrawable ld = (LayerDrawable) drawable;
                          final int num = ld.getNumberOfLayers();
                          for (int i = 0; i < num; i++) {
                              Drawable d = ld.getDrawable(i);
                              ld.setDrawableByLayerId(ld.getId(i), fromDrawable(d, r));
                          }
                          return ld;
                      }
      
                      Bitmap bm = drawableToBitmap(drawable);
                      if (bm != null) {
                          return new RoundCornerDrawable(bm, r);
                      } else {
                          Log.w(TAG, "Failed to create bitmap from drawable!");
                      }
                  }
                  return drawable;
              }
      
              public static Bitmap drawableToBitmap(Drawable drawable) {
                  if (drawable == null) {
                      return null;
                  }
      
                  if (drawable instanceof BitmapDrawable) {
                      return ((BitmapDrawable) drawable).getBitmap();
                  }
      
                  Bitmap bitmap;
                  int width = Math.max(drawable.getIntrinsicWidth(), 2);
                  int height = Math.max(drawable.getIntrinsicHeight(), 2);
                  try {
                      bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                      Canvas canvas = new Canvas(bitmap);
                      drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                      drawable.draw(canvas);
                  } catch (IllegalArgumentException e) {
                      e.printStackTrace();
                      bitmap = null;
                  }
                  return bitmap;
              }
      
              @Override
              public boolean isStateful() {
                  return mBorderColor.isStateful();
              }
      
              @Override
              protected boolean onStateChange(int[] state) {
                  int newColor = mBorderColor.getColorForState(state, 0);
                  if (mBorderPaint.getColor() != newColor) {
                      mBorderPaint.setColor(newColor);
                      return true;
                  } else {
                      return super.onStateChange(state);
                  }
              }
      
              private void configureBounds(Canvas canvas) {
                  // I have discovered a truly marvelous explanation of this,
                  // which this comment space is too narrow to contain. :)
                  // If you want to understand what's going on here,
                  // See http://www.joooooooooonhokim.com/?p=289
                  Rect clipBounds = canvas.getClipBounds();
                  Matrix canvasMatrix = canvas.getMatrix();
      
                  if (ScaleType.CENTER == mScaleType) {
                      mBounds.set(clipBounds);
                  } else if (ScaleType.CENTER_CROP == mScaleType) {
                      applyScaleToRadii(canvasMatrix);
                      mBounds.set(clipBounds);
                  } else if (ScaleType.FIT_XY == mScaleType) {
                      Matrix m = new Matrix();
                      m.setRectToRect(mBitmapRect, new RectF(clipBounds), Matrix.ScaleToFit.FILL);
                      mBitmapShader.setLocalMatrix(m);
                      mBounds.set(clipBounds);
                  } else if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType
                          || ScaleType.FIT_CENTER == mScaleType || ScaleType.CENTER_INSIDE == mScaleType) {
                      applyScaleToRadii(canvasMatrix);
                      mBounds.set(mBitmapRect);
                  } else if (ScaleType.MATRIX == mScaleType) {
                      applyScaleToRadii(canvasMatrix);
                      mBounds.set(mBitmapRect);
                  }
              }
      
              private void applyScaleToRadii(Matrix m) {
                  float[] values = new float[9];
                  m.getValues(values);
                  for (int i = 0; i < mRadii.length; i++) {
                      mRadii[i] = mRadii[i] / values[0];
                  }
              }
      
              private void adjustCanvasForBorder(Canvas canvas) {
                  Matrix canvasMatrix = canvas.getMatrix();
                  final float[] values = new float[9];
                  canvasMatrix.getValues(values);
      
                  final float scaleFactorX = values[0];
                  final float scaleFactorY = values[4];
                  final float translateX = values[2];
                  final float translateY = values[5];
      
                  final float newScaleX = mBounds.width()
                          / (mBounds.width() + mBorderWidth + mBorderWidth);
                  final float newScaleY = mBounds.height()
                          / (mBounds.height() + mBorderWidth + mBorderWidth);
      
                  canvas.scale(newScaleX, newScaleY);
                  if (ScaleType.FIT_START == mScaleType || ScaleType.FIT_END == mScaleType
                          || ScaleType.FIT_XY == mScaleType || ScaleType.FIT_CENTER == mScaleType
                          || ScaleType.CENTER_INSIDE == mScaleType || ScaleType.MATRIX == mScaleType) {
                      canvas.translate(mBorderWidth, mBorderWidth);
                  } else if (ScaleType.CENTER == mScaleType || ScaleType.CENTER_CROP == mScaleType) {
                      // First, make translate values to 0
                      canvas.translate(
                              -translateX / (newScaleX * scaleFactorX),
                              -translateY / (newScaleY * scaleFactorY));
                      // Then, set the final translate values.
                      canvas.translate(-(mBounds.left - mBorderWidth), -(mBounds.top - mBorderWidth));
                  }
              }
      
              private void adjustBorderWidthAndBorderBounds(Canvas canvas) {
                  Matrix canvasMatrix = canvas.getMatrix();
                  final float[] values = new float[9];
                  canvasMatrix.getValues(values);
      
                  final float scaleFactor = values[0];
      
                  float viewWidth = mBounds.width() * scaleFactor;
                  mBorderWidth = (mBorderWidth * mBounds.width()) / (viewWidth - (2 * mBorderWidth));
                  mBorderPaint.setStrokeWidth(mBorderWidth);
      
                  mBorderBounds.set(mBounds);
                  mBorderBounds.inset(- mBorderWidth / 2, - mBorderWidth / 2);
              }
      
              private void setBorderRadii() {
                  for (int i = 0; i < mRadii.length; i++) {
                      if (mRadii[i] > 0) {
                          mBorderRadii[i] = mRadii[i];
                          mRadii[i] = mRadii[i] - mBorderWidth;
                      }
                  }
              }
      
              @Override
              public void draw(Canvas canvas) {
                  canvas.save();
                  if (!mBoundsConfigured) {
                      configureBounds(canvas);
                      if (mBorderWidth > 0) {
                          adjustBorderWidthAndBorderBounds(canvas);
                          setBorderRadii();
                      }
                      mBoundsConfigured = true;
                  }
      
                  if (mOval) {
                      if (mBorderWidth > 0) {
                          adjustCanvasForBorder(canvas);
                          mPath.addOval(mBounds, Path.Direction.CW);
                          canvas.drawPath(mPath, mBitmapPaint);
                          mPath.reset();
                          mPath.addOval(mBorderBounds, Path.Direction.CW);
                          canvas.drawPath(mPath, mBorderPaint);
                      } else {
                          mPath.addOval(mBounds, Path.Direction.CW);
                          canvas.drawPath(mPath, mBitmapPaint);
                      }
                  } else {
                      if (mBorderWidth > 0) {
                          adjustCanvasForBorder(canvas);
                          mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
                          canvas.drawPath(mPath, mBitmapPaint);
                          mPath.reset();
                          mPath.addRoundRect(mBorderBounds, mBorderRadii, Path.Direction.CW);
                          canvas.drawPath(mPath, mBorderPaint);
                      } else {
                          mPath.addRoundRect(mBounds, mRadii, Path.Direction.CW);
                          canvas.drawPath(mPath, mBitmapPaint);
                      }
                  }
                  canvas.restore();
              }
      
              public void setCornerRadii(float[] radii) {
                  if (radii == null)
                      return;
      
                  if (radii.length != 8) {
                      throw new ArrayIndexOutOfBoundsException("radii[] needs 8 values");
                  }
      
                  for (int i = 0; i < radii.length; i++) {
                      mRadii[i] = radii[i];
                  }
              }
      
              @Override
              public int getOpacity() {
                  return (mBitmap == null || mBitmap.hasAlpha() || mBitmapPaint.getAlpha() < 255) ? PixelFormat.TRANSLUCENT
                          : PixelFormat.OPAQUE;
              }
      
              @Override
              public void setAlpha(int alpha) {
                  mBitmapPaint.setAlpha(alpha);
                  invalidateSelf();
              }
      
              @Override
              public void setColorFilter(ColorFilter cf) {
                  mBitmapPaint.setColorFilter(cf);
                  invalidateSelf();
              }
      
              @Override
              public void setDither(boolean dither) {
                  mBitmapPaint.setDither(dither);
                  invalidateSelf();
              }
      
              @Override
              public void setFilterBitmap(boolean filter) {
                  mBitmapPaint.setFilterBitmap(filter);
                  invalidateSelf();
              }
      
              @Override
              public int getIntrinsicWidth() {
                  return mBitmapWidth;
              }
      
              @Override
              public int getIntrinsicHeight() {
                  return mBitmapHeight;
              }
      
              public float getBorderWidth() {
                  return mBorderWidth;
              }
      
              public void setBorderWidth(float width) {
                  mBorderWidth = width;
                  mBorderPaint.setStrokeWidth(width);
              }
      
              public int getBorderColor() {
                  return mBorderColor.getDefaultColor();
              }
      
              public void setBorderColor(int color) {
                  setBorderColor(ColorStateList.valueOf(color));
              }
      
              public ColorStateList getBorderColors() {
                  return mBorderColor;
              }
      
              /**
               * Controls border color of this ImageView.
               *
               * @param colors
               *            The desired border color. If it's null, no border will be
               *            drawn.
               *
               */
              public void setBorderColor(ColorStateList colors) {
                  if (colors == null) {
                      mBorderWidth = 0;
                      mBorderColor = ColorStateList.valueOf(Color.TRANSPARENT);
                      mBorderPaint.setColor(Color.TRANSPARENT);
                  } else {
                      mBorderColor = colors;
                      mBorderPaint.setColor(mBorderColor.getColorForState(getState(),
                              DEFAULT_BORDER_COLOR));
                  }
              }
      
              public boolean isOval() {
                  return mOval;
              }
      
              public void setOval(boolean oval) {
                  mOval = oval;
              }
      
              public ScaleType getScaleType() {
                  return mScaleType;
              }
      
              public void setScaleType(ScaleType scaleType) {
                  if (scaleType == null) {
                      return;
                  }
                  mScaleType = scaleType;
              }
          }
      
      }
      

      styleable添加到res文件夹下的attr文件

      <declare-styleable name="RoundCornerImageView">
              <attr name="sriv_left_top_corner_radius" format="dimension" />
              <attr name="sriv_right_top_corner_radius" format="dimension" />
              <attr name="sriv_left_bottom_corner_radius" format="dimension" />
              <attr name="sriv_right_bottom_corner_radius" format="dimension" />
              <attr name="sriv_border_width" format="dimension" />
              <attr name="sriv_border_color" format="color" />
              <attr name="sriv_oval" format="boolean" />
              <attr name="android:scaleType" />
          </declare-styleable>
      

      在 XML 文件中使用:

       <com.skd.stackdemo.RoundCornerImageView
              android:layout_width="300dp"
              android:layout_height="300dp"
              android:src="@drawable/android"
              android:scaleType="centerCrop"
              app:sriv_left_top_corner_radius="0dp"
              app:sriv_right_top_corner_radius="20dp"
              app:sriv_left_bottom_corner_radius="0dp"
              app:sriv_right_bottom_corner_radius="0dp"
              app:sriv_oval="false" />
      

      上述代码的输出是:

      更多信息请查看这个github项目:SelectableRoundedImageView

      希望对你有用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-14
        • 2020-01-07
        • 1970-01-01
        • 1970-01-01
        • 2017-07-25
        • 1970-01-01
        • 1970-01-01
        • 2011-06-18
        相关资源
        最近更新 更多