Skip to content

渲染(Render)

Render渲染是将可视化内容展示在屏幕上的过程。在mui系统中,大部分渲染工作是通过onDraw方法完成的,而Drawable 类用于向画布(Canvas)上添加新的内容。对于一些常见的渲染需求,mui已经提供了Drawable的子类。

对于一个View,可以使用setBackground方法设置其背景渲染。特别地,对于CompoundButton,可以使用setButtonDrawable 设置其额外的渲染效果,但目前我们还没有测试出其具体作用。

Drawable

Drawable 是一个“可以被绘制的东西”的抽象类。通常,Drawable用作从资源中检索的绘制内容的类型, 它提供了一个通用的接口来处理各种形式的底层视觉资源(例如图片、纯色、线框)。 与View不同,Drawable不具备处理事件或与用户交互的功能(动画效果除外)。

ColorDrawable

ColorDrawable用于创建一个单一颜色的图形。通过传入一个colorInt值可以设置ColorDrawable的颜色。

  • 颜色混合模式:使用setTintBlendMode方法设置混合模式。具体可选项请参考icyllis.modernui.graphics.BlendMode类。
  • 设置边界:使用setBounds方法设置画布渲染的边界,坐标包括画布上位置的起始点和结束点。

⚠️ 注意

实际测试中可能未能如预期生效,这可能需要手动将其推送到画布上时才能体现效果。

  • 热点hotspot用于设置渲染热点,帮助实现与点击位置相关的UI特效。

ShapeDrawable

ShapeDrawable用于在指定位置绘制形状的图案。

⛔ 特别注意

在配置ShapeDrawable时,务必调用setUseLevelForShape(false),否则图形可能无法正确渲染。

  • 设置形状:通过setShape方法传入形状的索引编号。可用编号常量可在ShapeDrawable中找到。例如,圆形将绘制在中心,直径等于组件较短边的长度。
  • 设置颜色:默认颜色为黑色。使用setTint方法设置的颜色将优先应用,否则将尝试使用setColor方法设置的颜色。
  • 设置边缘:使用setStroke方法为形状边缘添加描边。
  • 设置圆角:使用setCornerRadius方法设置圆角半径。

ImageDrawable

ImageDrawable用于在指定位置渲染图片。

  • 构造方法:需要一个Image类实例。可以通过Image.create(namespace, path) 方法获取资源路径中的图片。路径中应指定文件的后缀,如.png.jpg

DrawableWrapper

DrawableWrapper是一种特殊的Drawable,用于对已有的Drawable进行额外处理,如缩放、裁剪等。具体内容和用法请参见相关文档。

DrawableContainer

DrawableContainer是一种特殊的Drawable,能够同时包含多个Drawable并根据一定规则选择使用。 最常用的子类是StateListDrawable,其特别之处在于可以为不同状态指定不同的Drawable。 状态可以在StateSet.get(StateSet.xxx)中找到。

  • 过渡时间:使用setEnterFadeDurationsetExitFadeDuration方法设置渲染变化的过渡时间。

以下是一个示例代码,摘自icyllis.modernui.mc.ui.ThemeControl#addBackground方法:

java
public static void addBackground(View view) {
    StateListDrawable background = new StateListDrawable();
    ShapeDrawable drawable = new ShapeDrawable();
    drawable.setShape(ShapeDrawable.RECTANGLE);
    drawable.setColor(0x80a0a0a0);
    drawable.setCornerRadius(view.dp(2));
    background.addState(StateSet.get(StateSet.VIEW_STATE_HOVERED), drawable);
    background.setEnterFadeDuration(250);
    background.setExitFadeDuration(250);
    view.setBackground(background);
}

这段代码创建了一个半透明白色圆角矩形,并将其添加到StateListDrawable中,指定在VIEW_STATE_HOVERED状态下显示,即鼠标悬停在组件上时。 最后,设置了淡入和淡出效果的持续时间为250毫秒。

Draw

java
void draw(@NonNull Canvas canvas);

这是Drawable类中最核心的方法,用于在画布上绘制内容。控制绘制内容的一些特性还需要使用Paint类。

渲染过程是顺序执行的,因此内容会从上到下依次绘制。后渲染的内容默认会覆盖之前渲染的内容(若要更改此行为,请参考前面提到的颜色混合模式设置)。

  • 颜色设置:可以使用setARGBsetRGBAsetColor方法设置颜色。
  • 获取大小:使用getBounds()方法获取默认的绘制范围。
  • 渲染图形
    • 使用drawRect方法绘制矩形;
    • 使用drawRoundRect方法绘制圆角矩形,传入的int值为圆角半径,并可以指定绘制哪些角;
    • 使用drawArc方法绘制扇形,其中startAngle是起始角度,默认水平向右顺时针,sweepAngle是扇形的角度范围,单位为度;
    • 使用drawBezier方法绘制贝塞尔曲线;
    • 使用drawImage方法绘制图片。

对于drawRectdrawRoundRect,可以使用其衍生的渐变填充方法drawRectGradientdrawRoundRectGradient ,在这些方法中可以指定目标四个角的着色,过程将忽略Paint中的预定颜色。

  • 裁剪画布:使用clipRect方法裁剪画布的范围。裁剪后,超出范围的部分将不被渲染。

  • 描边设置

    • setStroke方法设置是否开启描边模式,若关闭,则会填充图案;
    • setStrokeCap设置描边端点类型(见Paint.CAP_...);
    • setStrokeWidth设置描边宽度;
    • setStrokeJoin设置描边转折处的拐角形状;
    • setStrokeAlign设置描边的对齐方式(注:此功能尚未实现);
    • setStrokeMiter将描边转折变为弧形,参数为弧形角度。
  • 画布调整:使用scalerotate等方法调整缩放和旋转等效果。

目标位置定位

在渲染过程中,确定使用哪些参数作为定位数据是非常重要的。

  • 使用getLeftgetTopgetRightgetBottom获取组件相对于父组件的位置。以父组件的左上角为原点(0,0),对应的组件的边界位置。
  • 使用getPaddingLeftgetPaddingTopgetPaddingRightgetPaddingBottom获取与父组件边界的相对距离。

在画布(Canvas)和组件事件监听(EventListener )中,左上角是坐标原点(0,0)。例如,组件的右下角坐标为(getWidth(), getHeight()) ;若要让图片填充组件的右下角四分之一区域,其范围应为 [(width / 2F, height / 2F), (width, height)]。

总之,在处理渲染时,我们无需考虑与父组件的位置相关性,直接使用组件内的相对坐标系即可。