zoukankan      html  css  js  c++  java
  • Android 自定义View修炼-Android实现圆形、圆角和椭圆自定义图片View(使用BitmapShader图形渲染方法)

    一、概述

    Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的。实现圆角图片的方法其实不少,常见的就是利用Xfermode,Shader。本文直接继承ImageView,使用BitmapShader方法来实现圆形、圆角和椭圆的绘制,等大家看我本文的方法后,其他的类似形状也就都能举一反三来来画出来了。

    二、效果图:

    三、BitmapShader简介

    BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、

    我们这里只关注BitmapShader,构造方法:

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

    参数1:bitmap

    参数2,参数3:TileMode;

    TileMode的取值有三种:

    CLAMP 拉伸

    REPEAT 重复

    MIRROR 镜像

    如果大家给电脑屏幕设置屏保的时候,如果图片太小,可以选择重复、拉伸、镜像;

    重复:就是横向、纵向不断重复这个bitmap

    镜像:横向不断翻转重复,纵向不断翻转重复;

    拉伸:这个和电脑屏保的模式应该有些不同,这个拉伸的是图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;

    public   BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)

    调用这个方法来产生一个画有一个位图的渲染器(Shader)。

    bitmap   在渲染器内使用的位图

    tileX      The tiling mode for x to draw the bitmap in.   在位图上X方向花砖模式

    tileY     The tiling mode for y to draw the bitmap in.    在位图上Y方向花砖模式

    TileMode:(一共有三种)

    CLAMP  :如果渲染器超出原始边界范围,会复制范围内边缘染色。

    REPEAT :横向和纵向的重复渲染器图片,平铺。

    MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT 重复方式不一样,他是以镜像方式平铺。

    四、自定义圆形、圆角和椭圆的图片View的实现

    1. 测量View的大小

    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // TODO Auto-generated method stub
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            // 如果是绘制圆形,则强制宽高大小一致
            if (mType == TYPE_CIRCLE) {
                mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight());
                mRadius = mWidth / 2;
                setMeasuredDimension(mWidth, mWidth);
            }
    
        }

    2、设置BitmapShader和画笔Paint

    /**
         * 设置BitmapShader
         */
        private void setBitmapShader() {
            Drawable drawable = getDrawable();
            if (null == drawable) {
                return;
            }
            Bitmap bitmap = drawableToBitmap(drawable);
            // 将bitmap作为着色器来创建一个BitmapShader
            mBitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
            float scale = 1.0f;
            if (mType == TYPE_CIRCLE) {
                // 拿到bitmap宽或高的小值
                int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
                scale = mWidth * 1.0f / bSize;
    
            } else if (mType == TYPE_ROUND || mType == TYPE_OVAL) {
                // 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
                scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight() * 1.0f / bitmap.getHeight());
            }
            // shader的变换矩阵,我们这里主要用于放大或者缩小
            mMatrix.setScale(scale, scale);
            // 设置变换矩阵
            mBitmapShader.setLocalMatrix(mMatrix);
            mPaint.setShader(mBitmapShader);
    
        }

    3.最后就是绘制出来圆角、圆形和椭圆的图片,肯定在onDraw里面啦,根本原理就是使用了上面mBitmapShader渲染的画笔来绘制

    
    
    @Override
        protected void onDraw(Canvas canvas) {
    
            if (null == getDrawable()) {
                return;
            }
            setBitmapShader();
            if (mType == TYPE_CIRCLE) {
                canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);
            } else if (mType == TYPE_ROUND) {
                mPaint.setColor(Color.RED);
                canvas.drawRoundRect(mRect, mRoundRadius, mRoundRadius, mPaint);
            }else if(mType == TYPE_OVAL){
                canvas.drawOval(mRect, mPaint);
            }
        }

    五、视图布局实现

    这个很简单,就是3个自定义的view:

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:layout_marginTop="5dp"
            android:layout_marginBottom="25dp"
            android:orientation="vertical" >
    
            <com.czm.viewdrawtest.XCRoundAndOvalImageView
                android:id="@+id/cicleImageView"
                android:layout_width="200dp"
                android:layout_height="200dp"
                android:src="@drawable/img1" />
    
            <com.czm.viewdrawtest.XCRoundAndOvalImageView
                android:id="@+id/roundRectImageView"
                android:layout_width="200dp"
                android:layout_height="240dp"
                android:layout_marginTop="5dp"
                android:src="@drawable/img2" />
    
            <com.czm.viewdrawtest.XCRoundAndOvalImageView
                android:id="@+id/ovalImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:src="@drawable/img3" />
        </LinearLayout>
    
    </ScrollView>

    六、使用和测试自定义View

    上面直接绘制的自定义View写完了,下面就是使用这个View了,使用方法和普通的ImageView一样,当作普通控件使用即可。

    package com.czm.viewdrawtest;
    
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Window;
    import android.view.WindowManager;
    /**
     * 使用自定义ImageView
     * @author caizhiming
     *
     */
    public class MainActivity extends Activity {
    
        private XCRoundAndOvalImageView circleImageView;//圆形图片
        private XCRoundAndOvalImageView roundRectImageView;//圆角矩形图片
        private XCRoundAndOvalImageView ovalImageView;//椭圆图片
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //设置无标题  
            requestWindowFeature(Window.FEATURE_NO_TITLE);  
            //设置全屏  
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,   
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);  
            setContentView(R.layout.activity_main);
            
            initViews();
        }
        /**
         * 初始化Views
         */
        private void initViews(){
            circleImageView = (XCRoundAndOvalImageView)findViewById(R.id.cicleImageView);
            roundRectImageView = (XCRoundAndOvalImageView)findViewById(R.id.roundRectImageView);
            ovalImageView = (XCRoundAndOvalImageView)findViewById(R.id.ovalImageView);
            
            roundRectImageView.setType(XCRoundAndOvalImageView.TYPE_ROUND);
            roundRectImageView.setRoundRadius(100);
            
            ovalImageView.setType(XCRoundAndOvalImageView.TYPE_OVAL);
            ovalImageView.setRoundRadius(50);
            
        }
    }

    七、源码下载:

     真题园网http://www.zhentiyuan.com

    源码下载:http://download.csdn.net/detail/jczmdeveloper/8303717

  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/4187153.html
Copyright © 2011-2022 走看看