第2篇被日天兄吐槽太简单,这次就来详细讲一下。
首先准备好需要显示的图片素材,导入软件里面。

TouchGFX默认使用的字体是不支持中文的,这里我们新建一个楷体的字体。

创建自定义的文字内容,用在代码里面调用(这种相当于自定义的小字库)。

新建一个自定义控件,这个根据自己的喜好来就行。

创建一个scrollWheel控件(scrollWheel与scrollList比较接近。区别在于,scrollList:当滑动到某一个子单元时,触发回调。scrollWheel:当点击某一个子单元时,触发回调,这里我们想实现一个点击进入的手表菜单,所以需要使用scrollWheel),具体配置可以参见截图,配置项还是很好理解的。

生成代码,启动vs,准备编写代码。
先运行一下仿真看看。

存在两个问题,第一、子单元都是显示的闹钟。第二、不是圆弧显示。我们一个个解决。
实现自定义子单元显示
编写代码
MenuElement.hpp
#ifndef MENUELEMENT_HPP
#define MENUELEMENT_HPP
#include <gui_generated/containers/MenuElementBase.hpp>
#include <images/BitmapDatabase.hpp>
#include <texts/TextKeysAndLanguages.hpp>
#include <math.h>
class MenuElement : public MenuElementBase
{
public:
    MenuElement();
    virtual ~MenuElement() {}
    virtual void initialize();
    void setNumber(int no);
protected:
};
#endif // MENUELEMENT_HPP
MenuElement.cpp
#include <gui/containers/MenuElement.hpp>
MenuElement::MenuElement()
{
}
void MenuElement::initialize()
{
    MenuElementBase::initialize();
}
void MenuElement::setNumber(int no)
{
    //Unicode::itoa(no, textBuffer, TEXT_SIZE, 10);
    switch (no)
    {
    case 0:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CALL_80_80_00FF00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_PHONE));
        break;
    case 1:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CHAT_80_80_00940F_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_INFO));
        break;
    case 2:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_QR_CODE_SCANNER_80_80_FFFFFF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_QR));
        break;
    case 3:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_DEVICE_ACCESS_ALARM_80_80_0000FF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_ALARM));
        break;
    case 4:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_IMAGE_MUSIC_NOTE_80_80_FF0000_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_MUSIC));
        break;
    case 5:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_SOCIAL_SWITCH_ACCOUNT_80_80_00FFB3_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_BOOK));
        break;
    case 6:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_MAPS_DIRECTIONS_RUN_80_80_9000FF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_MOTION));
        break;
    case 7:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_ACTION_SETTINGS_80_80_FFEE00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_SET));
        break;
    default:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CALL_80_80_00FF00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_PHONE));
        break;
    }
}
因为每一个子控件都是独立的,如果想在界面里面对自定义控件进行操作,自定义控件需要提供一个对外的接口。
我们创建了一个叫void setNumber(int no);的函数,只要输入对应的索引就能控制控件显示不同的元素。
menuView.hpp
#ifndef MENUVIEW_HPP
#define MENUVIEW_HPP
#include <gui_generated/menu_screen/menuViewBase.hpp>
#include <gui/menu_screen/menuPresenter.hpp>
class menuView : public menuViewBase
{
public:
    menuView();
    virtual ~menuView() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
    virtual void scrollWheelUpdateItem(MenuElement& item, int16_t itemIndex);
protected:
};
#endif // MENUVIEW_HPP
menuView.cpp
#include <gui/menu_screen/menuView.hpp>
menuView::menuView()
{
}
void menuView::setupScreen()
{
    menuViewBase::setupScreen();
}
void menuView::tearDownScreen()
{
    menuViewBase::tearDownScreen();
}
void menuView::scrollWheelUpdateItem(MenuElement& item, int16_t itemIndex)
{
    item.setNumber(itemIndex);
}
主要是通过scrollWheelUpdateItem调用了item.setNumber(itemIndex)进行控制显示。scrollWheelUpdateItem函数由TouchGFX设计器自动生成,具体可见menuViewBase.cpp文件。
跑一下仿真看看。

已经可以正常显示了。
实现圆弧显示
不罗嗦,直接上代码
MenuElement.hpp
#ifndef MENUELEMENT_HPP
#define MENUELEMENT_HPP
#include <gui_generated/containers/MenuElementBase.hpp>
#include <images/BitmapDatabase.hpp>
#include <texts/TextKeysAndLanguages.hpp>
#include <math.h>
class MenuElement : public MenuElementBase
{
public:
    MenuElement();
    virtual ~MenuElement() {}
    virtual void initialize();
    void setNumber(int no);
    void offset(int16_t x);
    virtual void setY(int16_t y);
protected:
};
#endif // MENUELEMENT_HPP
MenuElement.cpp
#include <gui/containers/MenuElement.hpp>
MenuElement::MenuElement()
{
}
void MenuElement::initialize()
{
    MenuElementBase::initialize();
}
void MenuElement::setNumber(int no)
{
    switch (no)
    {
    case 0:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CALL_80_80_00FF00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_PHONE));
        break;
    case 1:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CHAT_80_80_00940F_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_INFO));
        break;
    case 2:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_QR_CODE_SCANNER_80_80_FFFFFF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_QR));
        break;
    case 3:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_DEVICE_ACCESS_ALARM_80_80_0000FF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_ALARM));
        break;
    case 4:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_IMAGE_MUSIC_NOTE_80_80_FF0000_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_MUSIC));
        break;
    case 5:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_SOCIAL_SWITCH_ACCOUNT_80_80_00FFB3_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_BOOK));
        break;
    case 6:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_MAPS_DIRECTIONS_RUN_80_80_9000FF_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_MOTION));
        break;
    case 7:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_ACTION_SETTINGS_80_80_FFEE00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_SET));
        break;
    default:
        icon.setBitmap(Bitmap(BITMAP_ICON_THEME_IMAGES_COMMUNICATION_CALL_80_80_00FF00_SVG_ID));
        text.setTypedText(touchgfx::TypedText(T_MENU_PHONE));
        break;
    }
}
void MenuElement::offset(int16_t x)
{
    icon.setX(30 + x);
    text.setX(120 + x);
}
void MenuElement::setY(int16_t y)
{
    MenuElementBase::setY(y);
    const int circleRadius = 300;
    y = y + getHeight() / 2 - 480 / 2;
    float x_f = circleRadius - sqrtf((float)((circleRadius * circleRadius) - (y * y)));
    int16_t x = (int16_t)(x_f + 0.5f);
    offset(x);
}
首先解释一下为啥重载setY,这次的代码菜单是上下滑动的,每一次滑动的时候都会改变控件Y的位置。
因为TouchGFX代码本身是不开源的,我们并不清楚scrollWheel是如何实现的setY,所以希望在原本的代码基础上,加入我们自定义的代码,所以调用了MenuElementBase::setY(y);这样就能保留原始实现。
接下来的代码就没啥好讲的了,就是通过不同的y计算出x在的位置,这样就能实现圆弧一样的滑动。
跑一下仿真,看看是否正常。

效果不错,下到单片机试试。

收工。
不错的教学,真是学习到了,谢谢分享
谢谢分享!