AWTK自定义控件篇

AWTK 自定义控件篇

一,前序

  之前上一篇文章中简单介绍了 AWTK 本身自带的控件(AWTK系统控件篇),但是实际上我们在写一些复杂的 UI 时候, AWTK 本身的控件其实是不够用的,尤其一些特殊的 UI 。这个时候我们该怎样办呢?
  现在就引入我们本章节中的自定义控件篇,我们自定义一些控件,给我们专属的程序使用,但是这些自定义的控件最终还是会接入到 AWTK 的体系中,遵循 AWTK 的消息循环机制,来保证 AWTK 整个逻辑不会乱套了,所以我们的自定义控件,简单的来说就是重载 AWTK 控件的各种虚函数。

二,了解控件结构

  在写自定义控件前,先了解一下 AWTK 控件的各种虚表函数指针:

/* awtk/src/base/widget.h 文件 */
struct _widget_vtable_t {
 /* 省略了一些成员变量,为了聚焦需要重载的虚表函数 */
  widget_create_t create;
  widget_get_prop_t get_prop;
  widget_set_prop_t set_prop;
  widget_invalidate_t invalidate;
  widget_find_target_t find_target;
  widget_get_prop_default_value_t get_prop_default_value;

widget_on_copy_t on_copy;
widget_on_keyup_t on_keyup;
widget_on_keydown_t on_keydown;
widget_on_wheel_t on_wheel;
widget_on_paint_background_t on_paint_background;
widget_on_paint_self_t on_paint_self;
widget_on_paint_children_t on_paint_children;
widget_on_paint_border_t on_paint_border;
widget_on_paint_begin_t on_paint_begin;
widget_on_paint_end_t on_paint_end;
widget_on_pointer_down_t on_pointer_down;
widget_on_pointer_move_t on_pointer_move;
widget_on_pointer_up_t on_pointer_up;
widget_on_context_menu_t on_context_menu;
widget_on_layout_children_t on_layout_children;
widget_on_add_child_t on_add_child;
widget_on_remove_child_t on_remove_child;
widget_on_attach_parent_t on_attach_parent;
widget_on_detach_parent_t on_detach_parent;
widget_on_event_t on_event;
widget_on_event_before_children_t on_event_before_children;
widget_on_destroy_t on_destroy;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

  上面的代码中,我们可以看到一个 widget 中有很多的函数指针,这些函数指针是用来给我们载重对应的触发事件用的,这就是 AWTK 的控件多态性的表现,但是这么多的函数指针,我们是不是要把所有的函数都重载呢?但是不需要,具体重载哪一些函数,就需要看我们实际的用法来决定,下面给出每个重载函数表的定义:

函数指针 用途
create 控件创建函数指针,一般都会重载,尤其是该控件有自己特有的成员变量的时候。
get_prop 控件获取对应的成员变量的函数指针,一般是获取 UI 中的 XML 定义的特有的成员变量。
set_prop 控件设置对应的成员变量的函数指针,一般是设置 UI 中的 XML 定义的其他特有的成员变量。
invalidate 调用 widget_invalidate 函数(刷新控件)结束后,会触发该函数指针,一般不需要重载。
find_target 在查找焦点是否落在该控件的函数
get_prop_default_value 用来补充 get_prop 的函数指针,一般只重载 set_prop 就足够了。
on_copy 调用 widget_clone 函数(克隆控件)后,会触发该函数指针
on_keyup 当鼠标焦点在该控件中,同时触发鼠标弹起事件后触发该函数指针。
on_keydown 当鼠标焦点在该控件中,同时触发鼠标按下事件后触发该函数指针。
on_wheel 当鼠标焦点在该控件中,同时触发鼠标滚轮事件后触发该函数指针。
on_paint_background 当绘制控件的背景的时候触发该函数指针
on_paint_self 当绘制控件的背景的时候触发该函数指针,同时会取代默认绘制函数,改用该函数指针来绘制。
on_paint_children 当绘制控件的子集对象的时候触发该函数指针,同时会取代默认的函数,改用该函数指针来绘制。
on_paint_border 当绘制控件的边框的时候触发该函数指针,同时会取代默认的函数,改用该函数指针来绘制。
on_paint_begin 当绘制控件之前的时候,触发该函数指针。
on_paint_end 当绘制控件完成后的时候,触发该函数指针。
on_pointer_down 当鼠标(或者触摸屏)点下在该控件中,触发该函数指针。
on_pointer_move 当鼠标(或者触摸屏)在该控件中移动,触发该函数指针。
on_pointer_up 当鼠标(或者触摸屏)弹起在该控件中,触发该函数指针。
on_context_menu 弹出上下文菜单后,触发该函数指针。
on_layout_children 重新布局子控件的时候,触发该函数指针。
on_add_child 添加子控件的时候,触发该函数指针。
on_remove_child 移除子控件的时候,触发该函数指针。
on_attach_parent 当前控件添加到父控件的时候,触发该函数指针。
on_detach_parent 当前控件被父控件移除的时候,触发该函数指针。
on_event 接受各种事件的回调函数,一般都会重载这个函数来接受控件触发的事件。
on_event_before_children 当鼠标按下后,回调查找其子对象前触发该函数指针。
on_destroy 当控件释放后,触发该函数指针,一般是为了释放特有的成员变量的时候才会重载该函数。

备注:

  1. on_keyup 和 on_keydown 是属于窗口管理器直接把按键发给自己才会触发的函数指针,一般我们不用到这么细,所以可以不用理。而 on_pointer_XXXXX 函数指针是鼠标或者触摸事件直接触发的。
  2. 一般自定义控件都是为了画特有的 UI 为主,所以一般都会重载 on_paint_XXXX 的函数指针为主。
  3. 如果控件有特有的成员变量,同时希望通过 xml 上面定义后,直接传给控件的话,就可以通过重载 set_prop 和 get_prop 函数来实现。

三,自定义控件代码

  这里打算抛砖引玉的做法,写一个简单的自定义控件,大概把上面的讲到的东西融入起来,让大家更加容易明白一点,这次只是简单写一个三角形的按钮控件,由于 AWTK 本身是不提供三角形的按钮,所以这个时候就需要用到自定义控件了,下面是创建自定义控件的步骤:

  1. 创建 triangle_button.h 文件,并写入下面的代码:
/* triangle_button.h */
#ifndef TK_TRANGLE_BUTTON_H
#define TK_TRANGLE_BUTTON_H

#include "base/widget.h"

BEGIN_C_DECLS

typedef struct _triangle_button_t {
widget_t widget;
/* 标记三角形向左还是向右 /
bool_t is_left;
/
标记按钮是否按下 */
bool_t pressed;
} triangle_button_t;

/**

  • @method triangle_button_create
  • 创建triangle_button对象
  • @annotation ["constructor", "scriptable"]
  • @param {widget_t*} parent 父控件
  • @param {xy_t} x x坐标
  • @param {xy_t} y y坐标
  • @param {wh_t} w 宽度
  • @param {wh_t} h 高度
  • @return {widget_t} 对象。
    /
    widget_t
    triangle_button_create(widget_t
    parent, xy_t x, xy_t y, wh_t w, wh_t h);

/**

  • @method triangle_button_cast
  • 转换为triangle_button对象(供脚本语言使用)。
  • @annotation ["cast", "scriptable"]
  • @param {widget_t*} widget triangle_button对象。
  • @return {widget_t} triangle_button对象。
    /
    widget_t
    triangle_button_cast(widget_t
    widget);

#define WIDGET_TYPE_TRANGLE_BUTTON "triangle_button"
#define WIDGET_PROP_IS_LEFT "is_left"

#define TRANGLE_BUTTON(widget) ((triangle_button_t*)(widget))

END_C_DECLS

#endif /TK_TRANGLE_BUTTON_H/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  1. 创建 triangle_button.c 文件,并写入下面的代码:
/* triangle_button.c  */
#include "tkc/mem.h"
#include "triangle_button.h"
#include "base/widget_vtable.h"

static ret_t triangle_button_on_paint_self(widget_t widget, canvas_t c)
{
/* 不想使用默认的画图方法 */
return RET_OK;
}

/* 因为在风格中定义了背景色,默认的 on_paint_background 函数会根据风格中的 bg_color 或者 fg_color 填充整个控件 /
/
因为这个控件是想让按钮呈现三角形的样子,所以就选择重载 on_paint_background 函数 /
static ret_t triangle_button_on_paint_background(widget_t
widget, canvas_t c)
{
xy_t left_part_x = 0;
xy_t right_part_x = 0;
/
获取控件风格 /
style_t
style = widget->astyle;
color_t trans = color_init(0, 0, 0, 0);
vgcanvas_t vg = canvas_get_vgcanvas(c);
triangle_button_t
triangle_button = TRANGLE_BUTTON(widget);
/* 获取风格中设置的 bg_color 颜色值 */
color_t color = style_get_color(style, STYLE_ID_BG_COLOR, trans);

<span class="token function">return_value_if_fail</span><span class="token punctuation">(</span>triangle_button <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">,</span> RET_BAD_PARAMS<span class="token punctuation">)</span><span class="token punctuation">;</span>


<span class="token keyword">if</span> <span class="token punctuation">(</span>color<span class="token punctuation">.</span>rgba<span class="token punctuation">.</span>a <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>triangle_button<span class="token operator">-&gt;</span>is_left<span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		left_part_x <span class="token operator">=</span> widget<span class="token operator">-&gt;</span>w<span class="token punctuation">;</span>
		right_part_x <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span>
	<span class="token punctuation">{<!-- --></span>
		left_part_x <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
		right_part_x <span class="token operator">=</span> widget<span class="token operator">-&gt;</span>w<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">/* 保存之前 vgcanvas 的状态 */</span>
	<span class="token function">vgcanvas_save</span><span class="token punctuation">(</span>vg<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">/* 使用 vgcanvas 来画出三角形的样子 */</span>
	<span class="token function">vgcanvas_begin_path</span><span class="token punctuation">(</span>vg<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">/* 因为 vgcanvas 画图的坐标是绝对坐标,相对整个程序来说的 */</span>
	<span class="token comment">/* 而 c-&gt;ox 等于控件的获取绝对坐标,y坐标同理 */</span>
	<span class="token function">vgcanvas_move_to</span><span class="token punctuation">(</span>vg<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>ox <span class="token operator">+</span> left_part_x<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>oy <span class="token operator">+</span> widget<span class="token operator">-&gt;</span>h <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">vgcanvas_line_to</span><span class="token punctuation">(</span>vg<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>ox <span class="token operator">+</span> right_part_x<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>oy<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">vgcanvas_line_to</span><span class="token punctuation">(</span>vg<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>ox <span class="token operator">+</span> right_part_x<span class="token punctuation">,</span> c<span class="token operator">-&gt;</span>oy <span class="token operator">+</span> widget<span class="token operator">-&gt;</span>h<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">vgcanvas_close_path</span><span class="token punctuation">(</span>vg<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">/* 设置填充颜色 */</span>
	<span class="token function">vgcanvas_set_fill_color</span><span class="token punctuation">(</span>vg<span class="token punctuation">,</span> color<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token comment">/* 开始填充 */</span>
	<span class="token function">vgcanvas_fill</span><span class="token punctuation">(</span>vg<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">/* 还原到之前 vgcanvas 的状态 */</span>
	<span class="token function">vgcanvas_restore</span><span class="token punctuation">(</span>vg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>


<span class="token keyword">return</span> RET_OK<span class="token punctuation">;</span>

}

static ret_t triangle_button_get_prop(widget_t widget, const char name, value_t v)
{
triangle_button_t
triangle_button = TRANGLE_BUTTON(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);

<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">tk_str_eq</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> WIDGET_PROP_IS_LEFT<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
	<span class="token comment">/* 获取控件中的 is_left 属性 */</span>
	<span class="token function">value_set_bool</span><span class="token punctuation">(</span>v<span class="token punctuation">,</span> triangle_button<span class="token operator">-&gt;</span>is_left<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">return</span> RET_OK<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> RET_NOT_FOUND<span class="token punctuation">;</span>

}

static ret_t triangle_button_set_prop(widget_t widget, const char name, const value_t v)
{
triangle_button_t
triangle_button = TRANGLE_BUTTON(widget);
return_value_if_fail(widget != NULL && name != NULL && v != NULL, RET_BAD_PARAMS);

<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">tk_str_eq</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> WIDGET_PROP_IS_LEFT<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
	<span class="token comment">/* 根据 UI 的 xml 文件中的属性设置控件中的 is_left 属性 */</span>
	triangle_button<span class="token operator">-&gt;</span>is_left <span class="token operator">=</span> <span class="token function">value_bool</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">return</span> RET_OK<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> RET_NOT_FOUND<span class="token punctuation">;</span>

}

static ret_t triangle_button_on_event(widget_t widget, event_t e)
{
uint16_t type = e->type;
triangle_button_t* triangle_button = TRANGLE_BUTTON(widget);
return_value_if_fail(widget != NULL, RET_BAD_PARAMS);

<span class="token comment">/* 如果鼠标点击在控件上面,会设置其风格状态,让其改变 bg_color 的颜色 */</span>
<span class="token keyword">switch</span> <span class="token punctuation">(</span>type<span class="token punctuation">)</span>
<span class="token punctuation">{<!-- --></span>
<span class="token keyword">case</span> EVT_POINTER_DOWN<span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span>
	triangle_button<span class="token operator">-&gt;</span>pressed <span class="token operator">=</span> TRUE<span class="token punctuation">;</span>
	<span class="token function">widget_set_state</span><span class="token punctuation">(</span>widget<span class="token punctuation">,</span> WIDGET_STATE_PRESSED<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">widget_grab</span><span class="token punctuation">(</span>widget<span class="token operator">-&gt;</span>parent<span class="token punctuation">,</span> widget<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>	
<span class="token keyword">case</span> EVT_POINTER_UP<span class="token punctuation">:</span> <span class="token punctuation">{<!-- --></span>
	<span class="token comment">/* 发送点击事件 */</span>
	pointer_event_t evt <span class="token operator">=</span> <span class="token operator">*</span><span class="token punctuation">(</span>pointer_event_t<span class="token operator">*</span><span class="token punctuation">)</span>e<span class="token punctuation">;</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>triangle_button<span class="token operator">-&gt;</span>pressed <span class="token operator">&amp;&amp;</span> <span class="token function">widget_is_point_in</span><span class="token punctuation">(</span>widget<span class="token punctuation">,</span> evt<span class="token punctuation">.</span>x<span class="token punctuation">,</span> evt<span class="token punctuation">.</span>y<span class="token punctuation">,</span> FALSE<span class="token punctuation">)</span><span class="token punctuation">)</span>
	<span class="token punctuation">{<!-- --></span>
		evt<span class="token punctuation">.</span>e <span class="token operator">=</span> <span class="token function">event_init</span><span class="token punctuation">(</span>EVT_CLICK<span class="token punctuation">,</span> widget<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">widget_dispatch</span><span class="token punctuation">(</span>widget<span class="token punctuation">,</span> <span class="token punctuation">(</span>event_t<span class="token operator">*</span><span class="token punctuation">)</span><span class="token operator">&amp;</span>evt<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">case</span> EVT_POINTER_DOWN_ABORT<span class="token punctuation">:</span>
<span class="token keyword">case</span> EVT_POINTER_LEAVE<span class="token punctuation">:</span>
	triangle_button<span class="token operator">-&gt;</span>pressed <span class="token operator">=</span> FALSE<span class="token punctuation">;</span>
	<span class="token function">widget_ungrab</span><span class="token punctuation">(</span>widget<span class="token operator">-&gt;</span>parent<span class="token punctuation">,</span> widget<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token function">widget_set_state</span><span class="token punctuation">(</span>widget<span class="token punctuation">,</span> WIDGET_STATE_NORMAL<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token keyword">default</span><span class="token punctuation">:</span>
	<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">return</span> RET_OK<span class="token punctuation">;</span>

}

static const char* const s_triangle_button_properties[] = { WIDGET_PROP_IS_LEFT, NULL };

const widget_vtable_t g_triangle_button_vtable = {
.size = sizeof(triangle_button_t), /* size 成员变量是给控件开辟内存时候使用的 /
.type = WIDGET_TYPE_TRANGLE_BUTTON, /
type 用来获取风格属性用来的 /
.create = triangle_button_create, /
重载 create 函数指针 /
.persistent_properties = s_triangle_button_properties, /
标记永久保存成员变量 /
.on_event = triangle_button_on_event, /
重载 on_event 函数指针 /
.set_prop = triangle_button_set_prop, /
重载 set_prop 函数指针 /
.get_prop = triangle_button_get_prop, /
重载 get_prop 函数指针 /
.on_paint_self = triangle_button_on_paint_self, /
重载 on_paint_self 函数指针 /
.on_paint_background = triangle_button_on_paint_background /
重载 on_paint_background 函数指针 */
};

widget_t triangle_button_create(widget_t parent, xy_t x, xy_t y, wh_t w, wh_t h)
{
widget_t widget = widget_create(parent, &g_triangle_button_vtable, x, y, w, h);
triangle_button_t
triangle_button = TRANGLE_BUTTON(widget);

triangle_button<span class="token operator">-&gt;</span>pressed <span class="token operator">=</span> FALSE<span class="token punctuation">;</span>

<span class="token keyword">return</span> widget<span class="token punctuation">;</span>

}

widget_t triangle_button_cast(widget_t widget)
{
return_value_if_fail(widget_is_instance_of(widget, &g_triangle_button_vtable), NULL);

<span class="token keyword">return</span> widget<span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  1. 注册到 AWTK 的控件列表中
/* window_main.c */
ret_t application_init(void)
{
	/* 把 triangle_button 控件注册到 awtk 的控件列表中 */
	widget_factory_register(widget_factory(), WIDGET_TYPE_TRANGLE_BUTTON, triangle_button_create);
	/* ................ */
	return RET_OK;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 在 UI 的 XML 中增加该控件
<!-- ui/main.xml -->
<window x="0" y="0" w="100%" h="100%" >
  <view x="c" y="m" w="50%" h="50%" >
    <triangle_button x="0" y="0" w="50%" h="100%" is_left="true" />
    <triangle_button x="50%" y="0" w="50%" h="100%" is_left="false" />
  </view>
</window>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 在 style 中增加控件的风格
<!-- style/default.xmll -->
<triangle_button>
  <style name="default" >
    <normal bg_color="#ff0000" />
    <pressed bg_color="#ffff00"/>
    <over bg_color="#ff0000" />
  </style>
</triangle_button>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  到这里的话,恭喜你可以通过打开 ui/main.xml 的 UI 来看到自定义控件了,如下图效果:
AWTK自定义控件篇

四,总结

  自定义控件是用来补充 AWTK 本身没有提供的控件,如果 AWTK 本身就存在这样的控件就没有必要自己重新写一个控件了,用 AWTK 本身的就可以了,上面的三角形按钮控件只是一个抛砖引玉的例子而已,其实自定义控件不单单可以显示不同的 UI, 还可以做到很多不同的功能,比如让子控件位移(如 slide_menu 控件效果)等等很多效果,所以希望大家多点去研究 AWTK 自带的控件,通过 AWTK 自带的控件来更加了解自定义控件的运行机理。
  附上上面自定义三角形控件的项目源码 github 地址 (https://github.com/WNsACE/CSDN_AWTK_DEMO/tree/master/awtk_diy_widget_demo)

备注:如果 awtk_diy_widget_demo 项目修改资源后重新编译,可以直接双击项目中的 assets_gen.bat 来编译资源。

上一篇:前端Button点击无反应--记一次Debug经历


下一篇:从 sCrypt 智能合约中访问区块链数据(3)