自定义控件(阴影,渐变)

一、阴影:

Paint 类定义了一个名为 setShadowLayer 的方法:

public void
setShadowLayer(float radius,float dx,float dy,int shadowColor), 参数意义如下:

radius:阴影半径

dx: x 方向阴影的偏移量

dy: y 方向阴影的偏移量

shadowColor: 阴影的颜色

阴影layer显示 影时,shaderlayer 有 两 种 类 型 : View.LAYER_TYPE_SOFTWARE 和View.LAYER_TYPE_HARDWARE, layer 的默认类型为 LAYER_TYPE_HARDWARE, 但阴影只能在

View.LAYER_TYPE_SOFTWARE 环 境 下 工 作 , 所 以 , 我 们 需 要 调 用 View 类 的 publicvoid
setLayerType(int layerType,Paint paint) 方 法 为 Paint 对 象 指 定 层 的 类 型 :

setLayerType(View.LAYER_TYPE_SOFTWARE, paint)。如想取消阴影则将radius设置为0.

ShaderView.java:

public class ShaderView extends View {
    private Paint paint;
    public ShaderView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ShaderView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(5);
        paint.setTextSize(100);
        this.setLayerType(View.LAYER_TYPE_SOFTWARE,paint);//设置为SOFTWARE才会实现阴影
        paint.setShadowLayer(10,1,1, Color.BLUE);//偏移度很小时则变成发光字体
        canvas.drawText("Android开发",100,100,paint);
        canvas.restore();
        paint.setShadowLayer(10,5,5,Color.GREEN);//如果想要取消阴影,则将Radius设为0即可
        canvas.drawText("Android,你好",100,400,paint);
    }
}

二、渐变

渐变种类有:

1. 线性渐变: LinearGradient

线性渐变( LinearGradient) 根据指定的角度、颜色和模式使用渐变颜色填充绘图区域。我们必须定义两个点( x0, y0)和( x1, y1),渐变的方向与这两个点的连线垂直,

LinearGradient 的构造方法如下:

<1>

public LinearGradient(float x0,float y0,float x1,float y1,int color0,int color1,TileMode tile):本方法用于两种颜色的渐变, 各参数意义如下:

x0、 y0: 用于决定线性方向的第一个点的坐标( x0, y0);

x1、 y1:用于决定线性方向的第二个点的坐标( x1, y1);

color0: 第一种颜色;

color1: 第二种颜色;

tile: 渐变模式

<2>

public LinearGradient(float x0,float y0,float x1,floaty1,int colors[],float positions[],TileMode tile), 这是一个功能更加强大的构造方法, 我们来看看该构造方法参数的作用:

x0、 y0:起始点的坐标

x1、 y1:终止点的坐标

colors:多种颜色

positions:颜色的位置(比例)

TileMode:渐变模式

参数 colors 和 positions 都是数组, 前者用于指定多种颜色,后者用于指定每种颜色的起始比例位置。 positions 数组中的元素个数与 colors 要相同, 且是 0 至 1 的数值, [0,1]是临界区,

如果小于 0 则当 0 处理, 如果大于 1 则当 1 处理。假如在绘图区域和渐变区域大小相同的情况下,colors 包含了三种颜色: red、 yellow、 green, 在渐变区域中这三种颜色的起始比例位置为 0、 0.3、

2. 径向渐变: RadialGradient

径向渐变是以指定的点为中心, 向四周以渐变颜色进行圆周扩散, 和线性渐变一样,支持两种或多种颜色。

<1>public RadialGradient(float x,floaty,float
radius,int color0,int
color1,TileMode tile), 该构造方法支持两种颜色, 下面是参数的作用:

x、 y: 中心点坐标

radius: 渐变半径

color0:起始颜色

color1:结束颜色

TileMode:渐变模式

<2>public RadialGradient(float x,floaty,float
radius,int colors[],float positions[],
TileModetile), 该构造方法支持 3 种或 3 种以上颜色的渐变, 各参数的作用如下:

x、 y: 中心点坐标

radius: 渐变半径

colors:多种颜色

positions:颜色的位置(比例)

TileMode:渐变模式

构造函数2用法如上;

3. 扫描渐变: SweepGradient

SweepGradient 类似于军事题材电影中的雷达扫?效果, 固定圆心, 将半径假想为有形并旋

转一周而绘制的渐变颜色。 SweepGradient 定义了两个主要的构造方法:

<1>public SweepGradient(float cx,float cy,int color0,int color1)

支持两种颜色的扫描渐变, 参数的作用如下:

cx、 cy:圆点坐标;

color0:起始颜色;

color1:结束颜色。

<2>public SweepGradient(float cx,float cy,int colors[],float positions[])

支持多种颜色的扫描渐变, 参数的作用如下:

cx、 cy:圆点坐标;

colors:多种颜色;

positions:颜色的位置(比例)。

4. 位图渐变: BitmapShader

位图渐变其实就是在绘制的图形中将指定的位图作为背景, 如果图形比位图小, 则通过渐变模式进行平铺, TileMode.CLAMP 模式不平铺, TileMode.REPEAT 模式表示平铺, TileMode.MIRROR

模式也表示平铺, 但是交错的位图是彼此的镜像, 方向相反。 可以同时指定水平和垂直两个方向的渐变模式。

构造方法:

public BitmapShader(Bitmap bitmap,TileMode tileX,TileMode tileY), 参数如下:

bitmap:位图;

tileX: x 方向的重复模式;

tileY: y 方向的重复模式。

5. 混合渐变: ComposeShader

混合渐变 ComposeShader是将两种不同的渐变通过位图运算后得到的一种更加复杂的渐变。

构造方法:

<1>public ComposeShader(Shader shaderA,Shader shaderB,Xfermode mode)

<2>public ComposeShader(Shader shaderA,Shader shaderB,Mode mode)

shaderA 和 shaderB 是两个渐变对象, mode 为位图运算类型, 16 种运算模式如图 5-15

所示:

代码中, shaderA 为位图渐变, shaderB 为线性渐变, 根据 Mode.SRC_ATOP 的运算规则,

shaderA 会全部显示( 此处为小机器人), shaderB 只显示二者相交部分并位于最上面( TOP)。

渐变效果代码:

public class RadialGradientView extends View {
    private int color[]={Color.GREEN,Color.BLUE,Color.RED};
    //private float position[]={0,0.5f,1};
    public RadialGradientView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RadialGradientView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Rect rect=new Rect(100,100,600,600);
        //1.径向渐变
        RadialGradient r=new RadialGradient(350,350,250, Color.BLUE,Color.YELLOW, Shader.TileMode.MIRROR);
        //2.线性渐变
      //  LinearGradient r=new LinearGradient(100,100,600,600,Color.RED,Color.GREEN, Shader.TileMode.CLAMP);
        //3.扫描渐变
       // SweepGradient r=new SweepGradient(350,350,Color.RED,Color.GREEN);
        //SweepGradient r=new SweepGradient(350,350,color,null);
        //4.位图渐变
//        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.boy);
//        BitmapShader r=new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
        //5.混合渐变
//        LinearGradient lg=new LinearGradient(100,100,600,600,Color.RED,Color.GREEN, Shader.TileMode.CLAMP);
//        Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.boy);
//        BitmapShader bs=new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
//        ComposeShader r=new ComposeShader(bs,lg, PorterDuff.Mode.SRC_ATOP);
        //公用部分
        Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setShader(r);
        canvas.drawRect(rect,paint);
        canvas.translate(0,500);
        canvas.drawOval(new RectF(rect),paint);
    }
}

渐变与Matrix

public void setLocalMatrix(Matrix localM), 该方法能和渐变结合,在填充渐变颜色的时候实现移位、旋转、缩放和拉斜的效果。

我们做一个旋转的圆, 圆内使用 SweepGradient 渐变填充,看起来像一张光盘。首先, 我们创建了一个 Matrix 对象 mMatrix, mMatrix 定义了以圆点为中心渐变的旋转效

果, 注意不是旋转 Canvas 而是旋转 SweepGradient。 onDraw()方法中不断调用 invalidate()重绘自己, 每重绘一次就旋转 2 度,于是就形成了一个旋转的动画。

SweepMatrixView.java:

public class SweepMatrixView extends View {
    private Paint mpaint=new Paint(Paint.ANTI_ALIAS_FLAG);
    private float mRotate;
    private Matrix matrix=new Matrix();
    private Shader mshader;
    private int[] color={ Color.GREEN,Color.RED,Color.BLUE};
    public SweepMatrixView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setFocusable(true);
        setFocusableInTouchMode(true);

        float x=100;
        float y=100;
        mshader=new SweepGradient(x,y,color,null);
        mpaint.setShader(mshader);
    }

    public SweepMatrixView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint =mpaint;
        float x=100;
        float y=100;
        canvas.translate(100,100);
        canvas.drawColor(Color.WHITE);
        matrix.setRotate(mRotate,x,y);
        mshader.setLocalMatrix(matrix);
        mRotate+=2;
        if(mRotate>=360){
            mRotate=0;
        }
        invalidate();
        canvas.drawCircle(x,y,100,paint);
    }
}

可以实现扫描渐变像光盘一样旋转。

时间: 2024-08-28 21:00:59

自定义控件(阴影,渐变)的相关文章

WPF window 子窗口反馈效果(抖动/阴影渐变)

原文:WPF window 子窗口反馈效果(抖动/阴影渐变) 当设置了owner的子窗口显示后,点击子窗口外部,需要一种反馈机制(反馈动画). 实现: 1.触发源 每次点击子窗口外部,即母窗口时,事件捕捉如下 HwndSource hwndSource = PresentationSource.FromVisual(this.Owner) as HwndSource;//窗口过程 hwndSource?.AddHook(WndProc); 也可以调用WindowInteropHelper,获取母

绘制图形-移动,旋转,阴影,渐变

// Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { UIBezierPath *path = [UIBezierPath bezierPath]; //绘图的起点坐标 [path moveToPoint:CGPointMa

Quartz2D 编程指南(二)变换、图案、阴影

概览 图形上下文 路径 颜色与颜色空间 变换 图案 阴影 渐变 透明层 Quartz 2D 中的数据管理 位图与图像遮罩 CoreGraphics 绘制 Layer 5.变换 简介 Quartz 2D 绘制模型定义了两种独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的本地分辨率). 当我们需要一个点或者显示文档时, Quartz 会将用户空间坐标系统映射到设备空间坐标系统.当前映射关系的变换矩阵称为 CTM(current transformation matrix). Qu

Unity 阴影淡入淡出效果中Shader常量 unity_ShadowFadeCenterAndType和_LightShadowData的问题

由于Universal Render Pipeline目前(2020年4月1日)把阴影淡入淡出这个功能竟然给取消了…我自己拿片元位置到相机位置的距离进行了一个淡化,但是阴影边缘老是被裁切…后来研究了一下Unity里面这个CBuffer是干嘛的.有一些结论,鉴于似乎没搜到,就发个博客吧... 至于这些东西为啥是这样…,我也不知道...反正人家Unity就是这么干的 unity_ShadowFadeCenterAndType决定了阴影消散的中心:xyz保存的是camPos +  normalize(

PxCook 点击设计稿即可生成代码前端,高效智能的设计研发工具,智能标注软件。

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] PxCook 像素大厨 设计师一键拖拽上传后,可智能标注.然后程序员点击pxcp即可生成css xml swift objective-c还有NativeReact的代码了.支持画板解析.项目 字多不看的话 (走心要听: 这次3.0版本相比于之前更加高效,易用.支持 Win & Mac ,并且是支持PS和Sketch全平台. 拖拽即用和一键流的理念我想都明白它易用性的含义.不但体现在设计稿导入上,智能标注和生成代码也是一样.

好的用户界面-界面设计的一些技巧

原文地址:http://www.cnblogs.com/Wayou/p/goodui.html 如此有用的文章我已记不得是什么时候发现的了,但在看完的那一刻便想将之翻译,分享给大家自己也受用. 时间过了很久,来到了2014年,终于静下心来花了大把时间连同图片一起译成了中文.像我这样业余的翻译六级分数只够及格的程序员,不敢说做到信雅达,但求意思到位. 1 尽量使用单列而不是多列布局 单列布局能够让对全局有更好的掌控.同时用户也可以一目了然内容.而多列而已则会有分散用户注意力的风险使你的主旨无法很好

用户界面设计经验分享:界面设计技巧分享

如此有用的文章我已记不得是什么时候发现的了,但在看完的那一刻便想将之翻译,分享给大家自己也受用. 时间过了很久,来到了2014年,终于静下心来花了大把时间连同图片一起译成了中文.像我这样业余的翻译六级分数只够及格的程序员,不敢说做到信雅达,但求意思到位. 1 尽量使用单列而不是多列布局 单列布局能够让对全局有更好的掌控.同时用户也可以一目了然内容.而多列而已则会有分散用户注意力的风险使你的主旨无法很好表达.最好的做法是用一个有逻辑的叙述来引导用户并且在文末给出你的操作按钮. 2 放出礼品往往更具

一些关于界面设计的技巧

最近做项目有些忙,百忙之中老师让我给新生讲下界面设计的知识o(╯□╰)o(只因自己会小弄些PS戳我),这就尴尬了讲什么好呢?偶然间看到刘哇勇前辈翻译过这篇文章,但是发现前辈第40点以后就没译了.我就打算在前辈的翻译的基础上把剩下的部分给翻译完(自己英语不是特别好,所以就模糊翻译了),一来加深自己对设计的理解,二来到时也可以和朋友一起分享这篇文章.做好一名合格的程序员,我们应该有一些自己对设计的理解,这样我们大局观才能更加宽广. 1 尽量使用单列而不是多列布局 单列布局能够让对全局有更好的掌控.同

MenuDrawer的使用

---恢复内容开始--- MenuDrawer框架是一个可以实现上下左右滑动的框架,在使用中可以在xml文件中配置也可以在java代码中实现效果的配置 可以以jar的形式或依赖的形式存在      用依赖的形式存在是方便修改MenuDrawer的源码 在xml中配置 <net.simonvt.menudrawer.OverlayDrawer   //以覆盖的形式出现   即在侧滑时侧滑菜单滑动主界面不会发生改变        android:id="@+id/drawer"   

【转】40个良好用户界面Tips

一个良好的用户界面应具有高转换率,并且易于使用.但要用户体验良好并不容易做到,下面我们整理了40个良好用户界面Tips,希望能对你有帮助! 1 尽量使用单列而不是多列布局 单列布局能够让对全局有更好的掌控.同时用户也可以一目了然内容.而多列而已则会有分散用户注意力的风险使你的主旨无法很好表达.最好的做法是用一个有逻辑的叙述来引导用户并且在文末给出你的操作按钮. 2 放出礼品往往更具诱惑力 给用户一份精美小礼品这样的友好举动再好不过了.具体来讲,送出礼品也是之有效的获得客户忠诚度的战术,这是建立在