Android 绘图Shader之BitmapShader
来源:互联网 发布:java链表反序 编辑:程序博客网 时间:2024/05/25 05:37
Shader
Shader在计算机图形领域叫做着色器,是一组提供给GPU的绘图指令,用于告诉GPU在绘图时应该怎么绘制并对绘制的物体进行色彩渲染。
Android中定义了几种Shader给Paint使用,在Paint绘制图像时对其设置不同的Shader,绘制出来的物体就会使用Shader提供的信息进行着色。
Shader的子类有:BitmapShader、LinearGradient、ComposeShader、RadialGradient、SweepGradient
BitmapShader
BitmapShader是使用一张指定的图片给Paint进行着色,在绘制的时候会根据设置的TileMode(平铺模式)和图像来形成不同的效果,其中TileMode有
如下三种:
CLAMP 这种模式在绘制的时候如果绘制区域超出提供的图片的尺寸,超出区域会使用超出部分的边缘颜色进行着色
REPEAT 这种模式在绘制的时候如果绘制区域超出提供的图片的尺寸,超出区域会重新使用完整的图片进行着色
MIRROR 这种模式在绘制的时候如果绘制区域超出提供的图片的尺寸,超出区域会重新使用完整的图片进行着色,并且呈镜面反转效果
BitmapShader构造函数:
/** * 唯一的一个构造函数,调用这个构造函数构造一个新的BitmapShader * * @param bitmap 用于着色的bitmap对象 * @param tileX 水平方向的平铺模式. * @param tileY 垂直方向的平铺模式. */public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY) {
BitmapShader实例
public class BitmapShaderView extends View { private Paint mPaint; private Shader mShader; /** * 用于给Paint着色的图片 */ private Bitmap mBitmap; public BitmapShaderView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initial(); } private void initial(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.sunwukong); resetShader(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); //使用设置了Shader的Paint进行绘制 canvas.drawRect(0,0,width,height,mPaint); } /** * 重新设置BitmapShader * @param tileX * @param tileY */ public void resetShader(Shader.TileMode tileX,Shader.TileMode tileY){ mShader = new BitmapShader(mBitmap, tileX, tileY); //调用Paint的setShader(Shader shader)方法设置BitmapShader mPaint.setShader(mShader); invalidate(); }}
在代码中提供了一个public方法resetShader来设置不同的平铺模式,这样可以达到动态变化的演示效果。
布局代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" ><com.example.debugm.BitmapShaderView android:id="@+id/shader_view" android:layout_width="match_parent" android:layout_height="100dp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="clamp" android:text="@string/bitmap_shader_clamp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="mirror" android:text="@string/bitmap_shader_mirror" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="repeat" android:text="@string/bitmap_shader_repeat" /></LinearLayout>
Activity代码:
public class MainActivity extends AppCompatActivity { private BitmapShaderView mShaderView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mShaderView = (BitmapShaderView)findViewById(R.id.shader_view); } public void clamp(View view){ mShaderView.resetShader(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); } public void repeat(View view){ mShaderView.resetShader(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); } public void mirror(View view){ mShaderView.resetShader(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR); }}
通过点击不同的按钮切换不同的平铺模式
CLAMP效果图:
REPEAT效果图:
MIRROR效果图:
BitmapShader实际应用
BitmapShader在实际开发中还是会用到的,比如实现圆形ImageView,圆角ImageView
以下效果和代码只做演示用,具体使用到项目中还需要考虑其他详细的因素和条件
BitmapShader实现圆形ImageView和圆角ImageView
效果图:
代码:
public class RoundImageView extends ImageView { private static final int RECTANGLE = 0; private static final int CIRCULAR = 1; private static final float DEFAULT_RADIUS = 50f; private float mRadius = DEFAULT_RADIUS; private int mRoundType = CIRCULAR; private Paint mPaint; private Bitmap mBitmap; private Shader mShader; public RoundImageView(Context context) { this(context,null); } public RoundImageView(Context context,AttributeSet attrs) { this(context, attrs,R.attr.roundImageViewStyle); } public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.RoundImageView, defStyleAttr, R.style.RoundImageViewStyle_Default); mRadius = a.getDimension(R.styleable.RoundImageView_android_radius,DEFAULT_RADIUS); mRoundType = a.getInt(R.styleable.RoundImageView_roundType, CIRCULAR); a.recycle(); initialShader(); } private void initialShader(){ mPaint = new Paint(); mPaint.setAntiAlias(true); mBitmap = BitmapUtils.drawable2bitmap(getDrawable()); if(mBitmap != null){ mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(mShader); } } private boolean isCircular(){ return mRoundType == CIRCULAR; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); /* *如果是圆形的话需要让View的宽高比例一样 */ if(isCircular()){ int width = Math.min(getMeasuredWidth(),getMeasuredHeight()); int height = Math.min(width,getMeasuredHeight()); setMeasuredDimension(width,height); } } @Override protected void onDraw(Canvas canvas) { if(getDrawable() == null){ return; } int width = getWidth(); int height = getHeight(); float radius; /* *如果是圆形则绘制圆形图片,否则绘制圆角矩形 */ if(isCircular()){ radius = width/2; canvas.drawCircle(width / 2,height / 2,radius,mPaint); }else{ radius = mRadius; canvas.drawRoundRect(0f,0f,width*1.0f,height*1.0f,radius,radius,mPaint); } }}
自定义属性:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="RoundImageView"> <attr name="android:radius" /> <attr name="roundType" format="enum"> <enum name="rectangle" value="0"/> <enum name="circular" value="1"/> </attr> </declare-styleable> <attr name="roundImageViewStyle" format="reference" /></resources>
布局代码:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:showDividers="middle" android:divider="@drawable/divider_vertical" > <com.example.debugm.RoundImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/sunwukong" /> <com.example.debugm.RoundImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:roundType="rectangle" android:radius="5dp" android:src="@drawable/sunwukong2" /></LinearLayout>
默认样式:
<!-- Base application theme. --><style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="roundImageViewStyle">@style/RoundImageViewStyle.Default</item></style><style name="RoundImageViewStyle.Default" parent="@android:style/Widget"> <item name="roundType">circular</item></style>
- Android 绘图Shader之BitmapShader
- shader初探之BitmapShader
- Shader 之 BitmapShader
- Android绘图之Shader
- Android绘图基础之Shader
- android--BitmapDrawable之BitmapShader
- Android Shader渲染器:BitmapShader图片渲染
- android绘图处理系列(一):bitmapShader和Xfermode
- Android游戏Graphics绘图之Shader类介绍
- Android中Canvas绘图之Shader使用图文详解
- Android中Canvas绘图之Shader使用图文详解
- Android 中 Canvas 绘图之 Shader 使用图文详解
- Android中Canvas绘图之Shader使用图文详解
- Android中Canvas绘图之Shader使用图文详解
- Android中Canvas绘图之Shader使用图文详解---转载
- Android BitmapShader
- Android学习笔记进阶16之BitmapShader
- Android学习笔记进阶16之BitmapShader
- go写的爬虫小程序
- 编写程序数一下 1到 100 的所有整数中出现多少次数字9
- android ble 开发的各种坑
- Windows下动过批处理指令在浏览器中打开指定文件中的URL地址
- 二进制存图至SqlServer
- Android 绘图Shader之BitmapShader
- iOS 11正式版即将来袭,这25个新功能你知道吗?
- Windows学习(012)--HOOK系列知识点
- 《android开发艺术探索笔记》Part7、Android动画深入分析
- 解决:CBitmapButtion在debug情况下,出现debug assertion failed的问题
- 直播发展如此迅猛,在未来会有哪些新的趋势?
- Slam研究点介绍
- 1066. 图像过滤(15)
- 简单的 html文件 转换为 jsp 文件 不损坏原文件实现