第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在的位置,这样就能实现圆弧一样的滑动。
跑一下仿真,看看是否正常。
效果不错,下到单片机试试。
收工。
不错的教学,真是学习到了,谢谢分享
谢谢分享!