Introduction
Flutter is a mobile application development kit for crafting high-quality native experiences on iOS and Android platforms in record time. Even though Flutter is enough to build great mobile apps, interactivity, such as map integration, is needed in order to increase the user experience.
Huawei Map Kit
Huawei Map Kit is a development kit and map service developed by Huawei to easily integrate map-based functions into your apps. The kit currently covers map data of more than 200 countries and regions, supports 40+ languages, provides UI elements such as markers, shapes, and layers to customize your map, and also enables users to interact with the map in your app through gestures and buttons in different scenarios.
With the recently released Huawei Map Kit Flutter Plugin, Huawei developers now can use these features and integrate map-based functions to their Flutter projects. Hence, in this article, to explore the kit and Huawei Services, we will try to build a mobile app featuring Huawei Map using the plugin and Flutter SDK.
HMS Core Github: https://github.com/HMS-Core/hms-flutter-plugin/tree/master/flutter-hms-map
Required Configurations
Before we get started, to use Huawei Map Kit, and also other Huawei Mobile Services, you should be a Huawei Developer Account holder. For more detailed information on Developer Accounts and how to apply for them, please refer to this link.
Creating an App
· Sign in to AppGallery Connect using your Huawei ID and create a new project to work with, by clicking My projects>Add Project button.
· Click Add App button to add a new application to your project by filling the required fields such as name, category, and default language.
· Map Kit APIs of your app is enabled by default, but just to be sure, you can check it from the Manage APIs tab of your project on AppGallery Connect. You can also refer to Enabling Services article if you need any help.
· Open your Android Studio and create a Flutter application. The package name of your Flutter application should be the same with the package name of your app which you created on AppGallery Connect.
· Android requires a Signing Certificate to verify the authenticity of apps. Thus, you need to generate a Signing Certificate for your app. If you don’t know how to generate a Signing Certificate please click here for related article. Copy your generated Keystore file to your android/app directory of your project.
A side note: Flutter project structure have folders, such as ios and android folders, which belongs to different platforms, by nature, yet Android Studio treats them as a Flutter project folders and throws errors on these files. For this reason, before changing anything related to Android platform, you should right click to your android folder on your project directory and select Flutter > Open Android module in Android Studio. You can easily modify the files and also generate Signing Certificates from the Android Studio window that opened after selection.
· After generating your Signing Certificate (Keystore) you should extract SHA-256 fingerprint using keytool, which provided by JDK, and add to the AppGallery Connect by navigating to the App Information section of your app. You may also refer to Generating Fingerprint from a Keystore and Add Fingerprint certificate to AppGallery Connect articles for further help.
Integrating HMS and Map Plugin to Your Flutter Project
You also need to configure your Flutter application in order to communicate with Huawei to use Map Kit.
· Add the Huawei Map Kit Flutter Plugin as a dependency to your project’s pubspec.yaml file and run flutter pub get command to integrate Map Plugin to your project.
Code:
dependencies:
flutter:
sdk: flutter
huawei_map: ^4.0.4+300
· Download the agconnect-services.json file from the App Information section of the AppGallery Connect and copy it to your android/app directory of your project.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Your project’s android directory should look like this after adding both agconnect-services.json and keystore file.
· Add the Maven repository address and AppGallery Connect plugin to the project level build.gradle (android/build.gradle) file.
Code:
buildscript {
repositories {
//other repositories
maven { url 'https://developer.huawei.com/repo/' }
}
dependencies {
//other dependencies
classpath 'com.huawei.agconnect:agcp:1.2.1.301'
}
}
allprojects {
repositories {
//other repositories
maven { url 'https://developer.huawei.com/repo/' }
}
}
· Open your app level build.gradle (android/app/build.gradle) file and add the AppGallery Connect plugin.
Code:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect' //Added Line
apply plugin: 'kotlin-android'
· In the same file (android/app/build.gradle), add the signing configurations, and change the minSdkVersion of your project as shown below.
Code:
android {
/*
* Other configurations
*/
defaultConfig {
applicationId "<package_name>" //Your unique package name
minSdkVersion 19 //Change minSdkVersion to 19
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
config{
storeFile file('<keystore_file>')
storePassword '<keystore_password>'
keyAlias '<key_alias>'
keyPassword '<key_password>'
}
}
buildTypes {
debug {
signingConfig signingConfigs.config
}
release {
signingConfig signingConfigs.config
}
}
}
· Finally, to call capabilities of Huawei Map Kit, apply for the following permissions for your app in your AndroidManifest.xml file.
Code:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
— To obtain the current device location following permissions are also needed to be declared in your AndroidManifest.xml file (on Android 6.0 and later versions, you need to apply for these permissions dynamically). But we won’t use the current location in our app, this step is optional.
Code:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Using Huawei Map Kit Flutter Plugin
Creating a Map
Now that we are ready to use Huawei’s Map features, let’s implement a simple map.
Huawei Map Kit Flutter Plugin provides a single widget, called HuaweiMap, for developers to easily create and manage map fragments. By using this widget, developers can enable or disable attributes or gestures of a map, set initial markers, circles, or other shapes, decide the map type, and also set an initial camera position to focus an area when the map is ready.
Let’s choose a random location from İstanbul as an initial camera position. While declaring the initial camera position, the zoom level, which indicates the value of magnification, and target, which indicates the latitude and longitude of the location, is required. You can find my target coordinates and zoom level below, which we will use while creating our map.
Code:
static const LatLng _center = const LatLng(41.027470, 28.999339);
static const double _zoom = 12;
Since now we have an initial position, we should implement the map itself. We will first create a simple Scaffold and set a simple AppBar, then create a HuaweiMap object as a Scaffold’s body. HuaweiMap object, as mentioned before, has different attributes which you can see below. The following code will create a HuaweiMap object that is full-screen, scrollable, tiltable, and also shows the buildings or traffic.
Code:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static const LatLng _center = const LatLng(41.027470, 28.999339);
static const double _zoom = 12;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Map Demo"),
centerTitle: true,
backgroundColor: Colors.red,
),
body: HuaweiMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: _zoom,
),
mapType: MapType.normal,
tiltGesturesEnabled: true,
buildingsEnabled: true,
compassEnabled: true,
zoomControlsEnabled: false,
rotateGesturesEnabled: true,
myLocationButtonEnabled: false,
myLocationEnabled: false,
trafficEnabled: true,
),
);
}
}
Considering creating a ‘clean’ map, I disabled myLocationEnabled, myLocationButtonEnabled and zoomControlsEnabled attributes of the map, but do not forget to explore these attributes by trying yourself since they are great to boost your user experience of your app.
Huawei Map
Resizing the Map
A full-screen map is not always useful in some scenarios, thus, since HuaweiMap is a standalone widget, we can resize the map by wrapping it to Container or ConstrainedBox widgets.
For this project, I will create a layout in Scaffold by using Expanded, Column, and Container widgets. The following code shows a HuaweiMap widget which fills only one-third of a screen.
Code:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static const LatLng _center = const LatLng(41.027470, 28.999339);
static const double _zoom = 12;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Locations"),
centerTitle: true,
backgroundColor: Colors.red,
),
body: Column(
children: [
Expanded(
child: Padding(
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2)),
child: HuaweiMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: _zoom,
),
mapType: MapType.normal,
tiltGesturesEnabled: true,
buildingsEnabled: true,
compassEnabled: true,
zoomControlsEnabled: false,
rotateGesturesEnabled: true,
myLocationButtonEnabled: false,
myLocationEnabled: false,
trafficEnabled: true,
),
),
),
),
Expanded(flex: 2, child: Container()),
],
),
);
}
}
Adding Interactivity by Using Markers and CameraUpdate
Let’s assume that we are building an app that shows different restaurant locations as markers on our HuaweiMap object. To do this, we will set some initial markers to our map using HuaweiMap widget’s markers field.
Markers field of the widget takes a Set of markers, hence we should first create a set of Marker objects. Then use them as initial markers for our HuaweiMap widget.
As you know, the two-third of our screen is empty, to fill the space we will create some Card widgets that hold the location’s name, motto, and address as a String. To reduce the redundant code blocks, I create a separate widget, called LocationCard, which returns a styled custom Card widget. To not lose the scope of this article, I will not share the steps of how to create a custom card widget but you may find its code from the project’s GitHub link.
Code:
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static const LatLng _center = const LatLng(41.027470, 28.999339);
static const double _zoom = 12;
//Marker locations
static const LatLng _location1 = const LatLng(41.0329109, 28.9840904);
static const LatLng _location2 = const LatLng(41.0155957, 28.9827176);
static const LatLng _location3 = const LatLng(41.0217315, 29.0111898);
//Set of markers
Set<Marker> _markers = {
Marker(markerId: MarkerId("Location1"), position: _location1),
Marker(markerId: MarkerId("Location2"), position: _location2),
Marker(markerId: MarkerId("Location3"), position: _location3),
};
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Locations"),
centerTitle: true,
backgroundColor: Colors.red,
),
body: Column(
children: [
Expanded(
child: Padding(
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2)),
child: HuaweiMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: _zoom,
),
mapType: MapType.normal,
tiltGesturesEnabled: true,
buildingsEnabled: true,
compassEnabled: true,
zoomControlsEnabled: false,
rotateGesturesEnabled: true,
myLocationButtonEnabled: false,
myLocationEnabled: false,
trafficEnabled: true,
markers: _markers, //Using the set
),
),
),
),
//Styled Card widgets
Expanded(flex: 2, child: Padding(
padding: EdgeInsets.all(8),
child: SingleChildScrollView(
child: Column(
children: [
LocationCard(
title: "Location 1",
motto: "A Fine Dining Restaurant",
address:
"Avrupa Yakası, Cihangir, 34433 Beyoğlu/İstanbul Türkiye",
),
LocationCard(
title: "Location 2",
motto: "A Restaurant with an Extraordinary View",
address:
"Avrupa Yakası, Hoca Paşa, 34110 Fatih/İstanbul Türkiye",
),
LocationCard(
title: "Location 3",
motto: "A Casual Dining Restaurant",
address:
"Anadolu Yakası, Aziz Mahmut Hüdayi, 34672 Üsküdar/İstanbul Türkiye",
)
],
),
),),
)],
),
);
}
}
Now we have some custom cards beneath the map object which also has some initial markers. We will use these custom cards as a button to zoom in the desired marker with a smooth camera animation. To do so, users can easily tab a card to see the zoomed-in location on a Huawei map and explore the surrounding without leaving the page.
Resized Map with Location Cards
Before turning cards into a button we should first set a HuaweiMapController object in order to provide a controller for HuaweiMap, then use this controller on HuaweiMap widgets onMapCreated field to pair map and its controller. Below, I created a controller, and with the help of a simple function, use it in our HuaweiMap object.
Code:
HuaweiMapController mapController;
void _onMapCreated(HuaweiMapController controller) {
mapController = controller;
}
/*
This section only shows the added line. Remaining code is not changed.
*/
child: HuaweiMap(
initialCameraPosition: CameraPosition(
target: _center,
zoom: _zoom,
),
onMapCreated: _onMapCreated, // Added Line
mapType: MapType.normal,
tiltGesturesEnabled: true,
/*
Rest of the code
*/
We now have a controller for non-user camera moves, so let’s use the controller. I wrapped the LocationCards with InkWell widget to provide an onTap functionality. There are several useful methods in plugins CameraUpdate class which enables us to zoom in, zoom out, or change camera position. We will use the newLatLngZoom method to zoom in the stated location then, by using the controller and animateCamera method, we will animate the camera move to our new camera location. You can find the wrapped LocationCard with the CameraUpdate and controller.
Code:
InkWell(
onTap: () {
CameraUpdate cameraUpdate =
CameraUpdate.newLatLngZoom(
_location1, _zoomMarker);
mapController.animateCamera(cameraUpdate);
},
child: LocationCard(
title: "Location 1",
motto: "A Fine Dining Restaurant",
address:
"Avrupa Yakası, Cihangir, 34433 Beyoğlu/İstanbul Türkiye",
)),
The used _zoomMarker variable is a constant double and has a value of 18. Also, the used _location1 variable is the variable we set while creating our markers.
After implementing these steps, tap a card and you will see a smooth camera move animation with the change of zoom level in your HuaweiMap widget. Voila!
As I mentioned before, you can also set some circles, polylines, or polygons similar to the markers. Furthermore, you can add some on-click actions both to your map and shapes or markers you set. Do not forget to explore other functionalities that Huawei Map Kit Flutter Plugin offers.
I am leaving the project’s GitHub link in case you want to check or try this example by yourself. You may also find LocationCard’s code and other minor adjustments that I made, from the link.
https://github.com/SerdarCanDev/FlutterHuaweiMapTutorial
Conclusion
Since Huawei created its own services, the demand for support to cross-platform frameworks such as Flutter, React Native, Cordova or Xamarin, is increased. To meet these demands Huawei continuously releasing plugins and updates in order to support its developers. We already learned how to use Huawei’s Map Kit in our Flutter projects, yet there are several more official plugins for Huawei Services to explore.
For further reading, I will provide some links in the “References and Further Reading” section including an article which showcases another service. You may also ask any question related to this article in the comments section.
https://developer.huawei.com/consumer/en/hms/huawei-MapKit
https://pub.dev/publishers/developer.huawei.com/packages
Sending Push Notifications on Flutter with Huawei Push Kit Plugin:
https://medium.com/huawei-developers/sending-push-notifications-on-flutter-with-huawei-push-kit-plugin-534787862b4d
Introduction
HarmonyOS is a future-proof distributed operating system open to you as part of the initiatives for the all-scenario strategy, adaptable to mobile office, fitness and health, social communication, and media entertainment, to name a few. Unlike a legacy operating system that runs on a standalone device, HarmonyOS is built on a distributed architecture designed based on a set of system capabilities. It is able to run on a wide range of device forms, including smartphones, tablets, wearables, smart TVs and head units.
In this article, we will create a simple pedometer application for lite wearable which will count each step user takes, distance covered and Heart rate. Also, for every 1000 steps completion, wearable device will vibrate.
Pedometer app will have 2 UI screens, first screen will have start button. Once user clicks on Start button, app will route to second screen which will show STEPS, BPM (heart rate) and METER/KM (total distance) covered.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Requirements
1) DevEco IDE
2) Lite wearable simulator (or lite wearable watch)
Implementation
First page, index.hml contains start button.
Code:
<div class="container">
<text class="title">Pedometer</text>
<text class="subtitle">Step Counter</text>
<image class= "image" src='/common/pedometer.png' ></image>
<input class="button" type="button" value="Start" onclick="start"></input>
</div>
index.css has style defined for first page.
Code:
.container {
display: flex;
justify-content: center;
align-items: center;
left: 0px;
background-color: #192841;
top: 0px;
flex-direction: column;
width: 454px;
height: 454px;
}
.title {
font-size:38px;
font-family: HYQiHei-65S;
justify-content: center;
}
.subtitle {
font-size:30px;
justify-content: center;
}
.button {
width: 200px;
height: 50px;
font-size: 30px;
margin-top: 15px;
background-color: indigo;
}
.image {
width: 128px;
height: 143px;
justify-content: center;
margin-bottom: 15px;
margin-left: 10px;
margin-top: 20px;
}
index.js contains the implementation of start button. Once user clicks on start button, app will route to second page stepcounter.hml
Code:
import router from '@system.router'
export default {
data: {
title: 'World'
},
start() {
router.replace({
uri: 'pages/stepcounter/stepcounter'
});
}
}
Second page, stepcounter.hml contains UI design for displaying step count, heart beat count and total distance covered.
Code:
<div class="container" onswipe="touchMove">
<image class= "image" src='/common/stepscount.png' ></image>
<text class="subtitle">{{stepcount}}</text>
<div class="seperator" ></div>
<image class= "image" src='/common/heartbeat.png' ></image>
<text class="subtitle">{{heartbeatcount}}</text>
<div class="seperator" ></div>
<image class= "image1" src='/common/jogging.png' ></image>
<text class="subtitle">{{distance}}</text>
</div>
stepcounter.css has style defined for second page.
Code:
.container {
flex-direction: column;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 454px;
height: 454px;
background-color: #192841;
}
.title {
font-size:38px;
font-family: HYQiHei-65S;
justify-content: center;
}
.subtitle {
font-size:30px;
color: lightgrey;
margin: 15px;
justify-content: center;
}
.seperator {
height: 1px;
width: 454px;
margin-bottom: 5px;
margin-top: 5px;
background-color: white;
}
.image {
width: 48px;
height: 48px;
justify-content: center;
margin-bottom: 5px;
}
.image1 {
width: 48px;
height: 48px;
justify-content: center;
margin-bottom: 5px;
margin-top: 15px;
}
stepcounter.js has implementation of various APIs.
1. Body state API
This API is used to listen for changes of the sensor wearing state. We will use this API to know if user is wearing wearable device or not.
Code:
// to listen the sensor wearing state, returns true if wear is in wrist
sensor.subscribeOnBodyState({
success: function(response) {
console.log('get on-body state value:' + response.value);
if(response.value === true) {
// get the heart rate
_this.getHeartBeatCount();
}
},
fail: function(data, code) {
console.log('fail to get on body state, code:' + code + ', data: ' + data);
},
});
For more, you can check https://forums.developer.huawei.com/forumPortal/en/topic/0202458325873420042
Article Introduction
In this article, I have explained to develop a Tic-Tac-Toe application for Huawei Lite wearable device using Huawei DevEco studio and using JS language in Harmony OS. Tic-Tac-Toe is a game for two players, X and O, who take turns marking the spaces in a 3×3 grid. The player who succeeds in placing three of their marks in a diagonal, horizontal, or vertical row will be a winner.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Huawei Lite Wearable
Requirements
1) DevEco IDE
2) Lite wearable watch (Can use simulator also)
New Project (Lite Wearable)
After installation of DevEco Studio, make new project.
Select Lite Wearable in Device and select Empty Feature Ability in Template.
After the project is created, its directory as shown in below displayed image.
hml files describe the page layout.
css files describe the page style.
js files process the interactions between pages and users.
The app.js file manages global JavaScript logics and application lifecycle.
The pages directory stores all component pages.
The common directory stores public resource files, such as media resources and .js files.
Integration process
Design the UI
Step 1: Add background image.
As the first step, we can create a UI that contains tictactoe cell boxes which will be filled by the user entries. Create and add the background image for tictactoe screen using stack component.
index.html
HTML:
<stack class="stack">
<image src='/common/wearablebackground.png' class="background"></image>
index.css
CSS:
.background {
width:454px;
height:454px;
}
.stack {
width: 454px;
height: 454px;
justify-content: center;
}
Step 2: Add title for game. Add the display text for the current player.
Add the storage text for player and gameOver string to display that is game over after the game is completed. Here we use conditional UI rendering that when the Boolean gameOver is true, then display the gameOverString.
index.html
HTML:
<text class="app-title">{{title}} </text>
<text class="sub-title">{{playerString}}
</text>
<div class="uiRow"if="{{gameOver}}" >
<text if="{{gameOver}}" class="app-title">{{gameOverString}}</text>
</div>
index.css
CSS:
.app-title{
text-align: center;
width: 290px;
height: 52px;
color: #c73d3d;
padding-top: 10px;
margin-bottom: 30px;
border-radius: 10px;
background-color: transparent;
}
.sub-title{
text-align: center;
width: 290px;
height: 52px;
color: #26d9fd;
padding-top: 10px;
border-radius: 10px;
background-color: transparent;
}
index.js
JavaScript:
title: "Tic Tac Toe",
playerString: "Player One - O",
Step 3: Add UI 3x3 grid call for application.
We need 3x3 matrix of text boxes. Use loop rendering for the boxes since all are similar boxes. I have added animation for the boxes to make it more appealing.
HTML:
<div class="boxRow" for="{{cellValue in gameEntries}}" tid="id" else>
<text class="cell" onclick="handleCellClick($idx, 0)" >{{cellValue[0]}}</text>
<text class="cell" onclick="handleCellClick($idx, 1)">{{cellValue[1]}}</text>
<text class="cell" onclick="handleCellClick($idx, 2)">{{cellValue[2]}}</text>
</div>
CSS:
.boxRow {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
width: 247px;
height: 64px;
background-color: #000000;
animation-name: Go;
animation-duration: 2s;
animation-delay: 0;
animation-timing-function: linear;
animation-iteration-count: infinite;
border-radius: 5px;
}
.cell {
display: flex;
text-align: center;
width: 75px;
height: 50px;
border-width: 1px;
color: #414343;
background-color: #FFD700;
border-color: #414343;
border-radius: 5px;
margin: 5px;
}
So to check the condition iterate through the entries in 3x3 array. We are converting 3x3 array element location to index of the grid using modulo and math functions.
Read full article
Result
Tips and Tricks
You can use Lite-wearable simulator for development. We can extend 3x3 grid for higher order Tic-Tac-Toe just by increasing game entry matrix to 5x5 or 7x7.
Conclusion
In this article, we have learnt how to create simple game app Tic-Tac-Toe using various Harmony OS UI components of course, there are a lot more things we could do here, like make the game actually multiplayer, so you can play with a friend.
References
https://developer.harmonyos.com/en/...ces/lite-wearable-syntax-hml-0000001060407093
Read full article
Well explained, what are all the limitations in Harmony OS?
Symptom
While developing a card, I used a pseudo-class for a component to implement a color changing effect. However, the color cannot be restored.
For example, the original background color was as follows.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
This figure shows the new background color after using the pseudo-class.
In normal cases, the card’s background color is changed upon tapping, and will return to the original color when you lift your finger.
This problem is caused by incomplete pseudo-classes for cards supported by Huawei Quick App Loader. Even so, there’s still an easy solution.
Solution
Simply add a tap event to the component using the pseudo-class. No logic processing is needed.
Sample code:
CSS:
<div class="sitetype_box" widgetid="8e4bf1ca-f716-46f8-8614-16d1b35002c5" onclick="test">
</div>
CSS style:
.sitetype_box {
flex-direction: column;
background-color:#FFBF00;
padding: dpConvert(0) dpConvert($elementsMarginHorizontalL) dpConvert(0) dpConvert($elementsMarginHorizontalL);
}
/** Pseudo-class */
.sitetype_box :active{
background-color: #E40078;
}
Method:
JavaScript:
test(){
console.log("message");
}
Reference:
Pseudo-classes for quick apps:
https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-style#h1-1578402521212
New member here
nice
wonderful sharing!!
Thanks
Nice
good
omg, I thought I am the only one with this problem, thanks for providing the solution
Thanks
Hello from pakistan
JessicajK said:
omg, I thought I am the only one with this problem, thanks for providing the solution
Click to expand...
Click to collapse
It's an honor to solve your problem.
Mayism said:
Symptom
While developing a card, I used a pseudo-class for a component to implement a color changing effect. However, the color cannot be restored.
For example, the original background color was as follows.
This figure shows the new background color after using the pseudo-class.
In normal cases, the card’s background color is changed upon tapping, and will return to the original color when you lift your finger.
This problem is caused by incomplete pseudo-classes for cards supported by Huawei Quick App Loader. Even so, there’s still an easy solution.
Solution
Simply add a tap event to the component using the pseudo-class. No logic processing is needed.
Sample code:
CSS:
<div class="sitetype_box" widgetid="8e4bf1ca-f716-46f8-8614-16d1b35002c5" onclick="test">
</div>
CSS style:
.sitetype_box {
flex-direction: column;
background-color:#FFBF00;
padding: dpConvert(0) dpConvert($elementsMarginHorizontalL) dpConvert(0) dpConvert($elementsMarginHorizontalL);
}
/** Pseudo-class */
.sitetype_box :active{
background-color: #E40078;
}
Method:
JavaScript:
test(){
console.log("message");
}
Reference:
Pseudo-classes for quick apps:
https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-style#h1-1578402521212
Click to expand...
Click to collapse
Mayism said:
Symptom
While developing a card, I used a pseudo-class for a component to implement a color changing effect. However, the color cannot be restored.
For example, the original background color was as follows.
This figure shows the new background color after using the pseudo-class.
In normal cases, the card’s background color is changed upon tapping, and will return to the original color when you lift your finger.
This problem is caused by incomplete pseudo-classes for cards supported by Huawei Quick App Loader. Even so, there’s still an easy solution.
Solution
Simply add a tap event to the component using the pseudo-class. No logic processing is needed.
Sample code:
CSS:
<div class="sitetype_box" widgetid="8e4bf1ca-f716-46f8-8614-16d1b35002c5" onclick="test">
</div>
CSS style:
.sitetype_box {
flex-direction: column;
background-color:#FFBF00;
padding: dpConvert(0) dpConvert($elementsMarginHorizontalL) dpConvert(0) dpConvert($elementsMarginHorizontalL);
}
/** Pseudo-class */
.sitetype_box :active{
background-color: #E40078;
}
Method:
JavaScript:
test(){
console.log("message");
}
Reference:
Pseudo-classes for quick apps:
https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-style#h1-1578402521212
Click to expand...
Click to collapse
Mayism said:
Symptom
While developing a card, I used a pseudo-class for a component to implement a color changing effect. However, the color cannot be restored.
For example, the original background color was as follows.
This figure shows the new background color after using the pseudo-class.
In normal cases, the card’s background color is changed upon tapping, and will return to the original color when you lift your finger.
This problem is caused by incomplete pseudo-classes for cards supported by Huawei Quick App Loader. Even so, there’s still an easy solution.
Solution
Simply add a tap event to the component using the pseudo-class. No logic processing is needed.
Sample code:
CSS:
<div class="sitetype_box" widgetid="8e4bf1ca-f716-46f8-8614-16d1b35002c5" onclick="test">
</div>
CSS style:
.sitetype_box {
flex-direction: column;
background-color:#FFBF00;
padding: dpConvert(0) dpConvert($elementsMarginHorizontalL) dpConvert(0) dpConvert($elementsMarginHorizontalL);
}
/** Pseudo-class */
.sitetype_box :active{
background-color: #E40078;
}
Method:
JavaScript:
test(){
console.log("message");
}
Reference:
Pseudo-classes for quick apps:
https://developer.huawei.com/consumer/en/doc/development/quickApp-References/quickapp-style#h1-1578402521212
Click to expand...
Click to collapse