Android自定义圆角以及向下箭头的ImageView

尊重原创,转载请注明出处:http://blog.csdn.net/dreamsever/article/details/76615281

圆形图片ImageView以及圆角ImageView,我相信大家在网上都可以找到,但是有时候像弹窗类型的图片效果怎么实现呢?既有圆角,下面或者上下左右还有一个小的下角凸出来,关键是给人的感觉还像是把这个图片切成这个样子的。我尝试使用Android中shape给它加一个框来实现这种效果但是没办法出现下面的角。最终我选择了自定义

废话不多说先看效果图:

这里写图片描述

关键代码就是一个自定义的ImageView:

/**
 * 弹窗气泡效果的ImageView
 * Created by dream on 17/8/1.
 */

public class PopupImageView extends android.support.v7.widget.AppCompatImageView{

    private Paint paint;
    private Path muskPath;
    private int roundRadius;//圆角半径
    private int angleHeight;//下角高度
    private float percent=0.3f;//下角在底部的左边占据百分比
    private Bitmap mRectMask;
    private Xfermode mXfermode;

    public PopupImageView(Context context) {
        this(context, null);
    }

    public PopupImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void init(AttributeSet attrs) {
        paint=new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.PopupImageView);
        roundRadius = typedArray.getDimensionPixelOffset(R.styleable.PopupImageView_roundRadius,0);
        angleHeight = typedArray.getDimensionPixelOffset(R.styleable.PopupImageView_angleHeight,0);
        percent = typedArray.getFloat(R.styleable.PopupImageView_anglePercent,0);
        // 关键方法
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int id = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG);
        super.onDraw(canvas);
        Drawable drawable = getDrawable();
        if (null != drawable) {
            createMask();
            // 关键方法
            paint.setXfermode(mXfermode);
            canvas.drawBitmap(mRectMask, 0, 0, paint);
            paint.setXfermode(null);
            canvas.restoreToCount(id);
        }

    }

    /**
     * 获取上层蒙层
     */
    private void createMask() {
        if (mRectMask==null){
            int maskWidth = getMeasuredWidth();
            int maskHeight = getMeasuredHeight();
            mRectMask = Bitmap.createBitmap(maskWidth, maskHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(mRectMask);

            muskPath=new Path();
            muskPath.moveTo(roundRadius,0);
            muskPath.lineTo(maskWidth-roundRadius,0);
            muskPath.arcTo(new RectF(maskWidth-roundRadius*2,0,maskWidth,roundRadius*2),270,90);
            muskPath.lineTo(maskWidth,maskHeight-roundRadius-angleHeight);
            muskPath.arcTo(new RectF(maskWidth-roundRadius*2,maskHeight-roundRadius*2-angleHeight,maskWidth,maskHeight-angleHeight),0,90);
            muskPath.lineTo(maskWidth*percent+angleHeight,maskHeight-angleHeight);
            muskPath.lineTo(maskWidth*percent,maskHeight);
            muskPath.lineTo(maskWidth*percent-angleHeight,maskHeight-angleHeight);
            muskPath.lineTo(roundRadius,maskHeight-angleHeight);
            muskPath.arcTo(new RectF(0,maskHeight-roundRadius*2-angleHeight,roundRadius*2,maskHeight-angleHeight),90,90);
            muskPath.lineTo(0,roundRadius);
            muskPath.arcTo(new RectF(0,0,roundRadius*2,roundRadius*2),180,90);

            canvas.drawPath(muskPath,paint);

        }
    }
}

attr:

<declare-styleable name="PopupImageView">
   <attr name="roundRadius" format="dimension"/>
   <attr name="angleHeight" format="dimension"/>
   <attr name="anglePercent" format="float"/>
</declare-styleable>

使用:

<com.test.second.view.PopupImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:roundRadius="5dp"
        app:angleHeight="4dp"
        app:anglePercent="0.25"
        android:scaleType="fitXY"
        android:layout_centerInParent="true"
        android:src="@mipmap/afa"/>

如果你仅仅想实现上面的效果,那么上面的代码直接拿去就好了。假如上面的效果还不够满足你的需求或者你还想知其所以然,你可以看看下面的简单讲解也许可以给你一些启发。

原理简单讲解

这里的难点就两个,一个是Xfermode是什么鬼干嘛用的,一个是Path的绘制与计算

1、关于Xfermode 以及paint.setXfermode(mXfermode)

如果你想深入了解Xfermode一下我推荐两篇博客:

http://www.jianshu.com/p/d11892bbe055
http://blog.csdn.net/tianjian4592/article/details/44783283/

当然网上也有很多篇关于Xfermode的博客,没看懂还可以百度去看看其他人的。“setXfermode这个方法用于设置图像的过渡模式,所谓过渡是指图像的饱和度、颜色值等参数的计算结果的图像表现“。这句话有点难理解,其实这个方法的作用就是画笔绘制的时候决定上下两张图的重叠显示的效果。比如我们想要显示圆角图片,那么我们就需要一个圆角的蒙板,只显示蒙板与图片重叠的部分,其他部分透明或不可见,这里我们使用了PorterDuff.Mode.DST_IN。
Dst是下面的图,也就是先画的图;Source是上面的图,也就是后面要画的图。下图可以看出蓝色方块是上面的图,黄色的圆是下面的图,当采用DST_IN时只显示了黄色的圆角,也即是下面的图与上面的图重合部分且显示下面的图,上面的图透明。我们采用的也是PorterDuff.Mode.DST_IN,这样应该就可以了解为什么显示的是圆角图片了

这里写图片描述

2、Path的绘制与计算

这个我可以脸皮厚的说“无他, 但手熟尔。“吗

其实这里我们只需要画一个圆角的蒙板,准确的说还有一个小角。绘制path就是将一个点一个点的连起来,准备工具:画布,画笔,圆角半径,小角高度,path对象,好开始

Canvas canvas = new Canvas(mRectMask);
muskPath=new Path();
muskPath.moveTo(roundRadius,0);

这里写图片描述

看了上面这张图你应该就清楚的知道画这个Path的套路了,还有下面的小角,

这里写图片描述

关于Path的lineTo(),arcTo()方法的作用我建议自己查阅资料理解,还有也许你的需求是小角面朝左边,我相信当你看懂这里Path的绘制你就可以自己做出来像左边或右边的效果。

---end

这里写图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android ImageView 圆角可以通过以下两种方式实现: 1. 使用 XML 属性设置圆角ImageView 的 XML 布局文件中,可以使用以下属性设置圆角: ``` android:background="@drawable/your_image" android:scaleType="centerCrop" android:clipToOutline="true" android:outlineProvider="background" ``` 其中,`your_image` 是你要显示的图片资源。`scaleType` 属性设置图片的缩放方式,`clipToOutline` 属性设置是否裁剪视图的轮廓,`outlineProvider` 属性设置视图的轮廓提供者,这里使用 `background` 表示使用视图的背景作为轮廓。 然后,在 `res/drawable` 目录下创建一个 XML 文件,命名为 `your_image.xml`,内容如下: ``` <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="10dp" /> </shape> ``` 其中,`radius` 属性设置圆角的半径大小。 2. 使用代码设置圆角 在 Java 代码中,可以使用以下方法设置圆角: ``` ImageView imageView = findViewById(R.id.image_view); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_image); RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap); roundedBitmapDrawable.setCornerRadius(10); imageView.setImageDrawable(roundedBitmapDrawable); ``` 其中,`your_image` 是你要显示的图片资源。`RoundedBitmapDrawableFactory.create()` 方法创建一个圆角位图,`setCornerRadius()` 方法设置圆角的半径大小,`setImageDrawable()` 方法设置 ImageView 的显示内容为圆角位图。 以上两种方法都可以实现 ImageView 圆角的效果,具体使用哪种方式取决于你的需求和习惯。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值