I'm developing an app with Ionic 4/Angular 7/Angular Material 7.
In a screen there's a stepper.
Inside each stepper there's complex forms. Given its complexity I put this form inside components.
Inside the second step there's a radio group. When I open the second step I can set focus on a radio with keyboard, but can't select a radio button. The radio button get a grey circle around but not the color of selection.
In the first step there's also a radio group and in the initial state I can select it using keyboard. But if I open the second step and open the first step again the radio buttons are not selectable too.
I've simulated the situation without components inside the steppers and I was not able to reproduce the problem this way. Then I deduce the problem is caused by the component inside a step after this step is open.
How can I be able to correctly select the radio buttons inside a step?
Palliatively solved through a directive:
import { Directive, HostListener } from '#angular/core';
import { MatRadioButton } from '#angular/material';
#Directive({
selector: 'mat-radio-button'
})
export class MatRadioCorrectionDirective {
constructor(private host:MatRadioButton) { }
#HostListener('keyup', ['$event'])
onKeyup(event: KeyboardEvent) {
// console.log(event);
if(
event.keyCode == 38 // arrow up
|| event.keyCode == 40 // arrow down
|| event.keyCode == 37 // arrow left
|| event.keyCode == 39 // arrow right
) {
event.preventDefault();
this.host.checked = true;
// TODO: send event
this.host.change.emit(null);
// setTimeout(() => {
// }, 500);
}
}
}
I would want to build an Android TV app using React-Native. I have followed up the recommendation on this document: Building For TV Devices.
After, update the AndroidManifest.xml file I run the application using the command line - react-native run android. The app running without any issue; however, I tried to use the Directional-pad option from android emulator TV (720p) API 23 emulator and it didn't work. I was expecting to catch the event listed on the code below and write to the console respective test for each event. On the other hand, even the component that was used for text didn't get highlighted either focus on when I try to navigate using Directional-pad.
I am reaching out to the community to see if someone had this issue in the past and what was your issue and what you have done to resolve it? Also, as I am listing the steps below, if you could let me know if I missing something?
Please, let me know if you need any extra information in order to help me.
react-native init Dpad
cd Dpad
Update code based on - Building For
TV Devices
Start Android TV (720p) API 23 emulator.
react-native run-android
ANNEX:
Android TV (720p) API 23
Here is the code:
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import Channel from '../channel/channel.component';
import styles from './presentation.component.styles';
var TVEventHandler = require('TVEventHandler');
export default class Grid extends Component {
constructor(props){
super(props);
this.state = {
command: 'undefined'
}
}
setcomand( command) {
this.setState( () => { return { command: command }; });
}
_tvEventHandler: null;
_enableTVEventHandler() {
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function(cmp, evt) {
if (evt && evt.eventType === 'right') {
setcomand('Press Right!');
} else if(evt && evt.eventType === 'up') {
setcomand('Press Up!');
} else if(evt && evt.eventType === 'left') {
setcomand('Press Left!');
} else if(evt && evt.eventType === 'down') {
setcomand('Press Down!');
}
});
}
_disableTVEventHandler() {
if (this._tvEventHandler) {
this._tvEventHandler.disable();
delete this._tvEventHandler;
}
}
componentDidMount() {
this._enableTVEventHandler();
console.warn("component did mount");
}
componentWillUnmount() {
this._disableTVEventHandler();
console.warn("component Will Unmount");
}
render() {
return (
<View style={styles.container}>
<Text>{this.state.command}</Text>
<Channel name="Globo" description="Its brazilian TV channles for news"/>
<Channel name="TVI" description="Its Portuguese TV channles for news"/>
<Channel name="TVI" description="Its Portuguese TV channles for news"/>
</View>
);
}
}
I'm also struggling with this problem for a month. Still can't find help/solution.
I testing this on Android Studio Emulator and also on few real android TV boxes with real remote d-pads.
I still can't figure out if it's React Native problem (bug) or Android TV devices don't emit response (keyCode) on directional d-pad arrows.
I can reproduce events like: focus, blur, select, fastForward, playPause, rewind, but no way to get events like e.g. "left".
I search a lot of google and other sites, you are first one who struggling with same issue.
I feel like no one cares about Android TV in React-Native.
You can also comment my Issue thread on React-Native github page.
https://github.com/facebook/react-native/issues/20924
I hope we figure it out soon.
Cheers
I was not able to verify that Directional-pad works with react-native. That was my goal of this demo. I am learning to build android Tv using react-native and so far Directional-pad it's being a big challenge given that TV user won't use touch screen event.
However, I couldn't find out why my app was not responding to the Directional-pad keyboard (left, right, up and down). There was no code error.
Have you tried to use Directional-pad to navigate on your react-native app?
Thank you,
Dave -
I decided to develop Android TV app using React Native because the video that react-native team shared - [https://www.youtube.com/watch?v=EzIQErHhY20] and the tutorial page [https://facebook.github.io/react-native/docs/building-for-apple-tv]. I think that's everything we have; other than that we won't get further support.
GOOD NEWS - I have started a new project from scratch using react native version 0.57.0, node version V10.7.not and **npm Version 4.6.1. Also, for navigation, I am using react-navigation version 2. I was able to see that my Directional-pad emulator was working, however, I was not able to see the focus on the element that I am navigating (left, right, down, up).
I will be working to see how I can fix the focus issue.
Let's keeping share our progress and feel free to reach out.
Thank you,
Justimiano Alves
use this code and u can see the console on debugger
_tvEventHandler: any;
_enableTVEventHandler() {
var self = this;
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function (cmp, evt) {
console.log("kcubsj"+evt.eventType)
if (evt && evt.eventType === 'right') {
console.log('right');
} else if (evt && evt.eventType === 'up') {
console.log('up');
} else if (evt && evt.eventType === 'left') {
console.log('left');
} else if (evt && evt.eventType === 'down') {
console.log('down');
} else if (evt && evt.eventType === 'select') {
//self.press();
}
});
}
_disableTVEventHandler() {
if (this._tvEventHandler) {
this._tvEventHandler.disable();
delete this._tvEventHandler;
}
}
componentDidMount() {
this._enableTVEventHandler();
}
componentWillUnmount() {
this._disableTVEventHandler();
}
I have really good news about support for D-Pad arrow events (up, down, left, right).
It turned out that one of Android TV contributor for react-native is person from my country. I reach out contact with him and tell about this problem. He check that out and actually, there is missing code for that.
He made pull request to support that in react-native. It should be fixed in one of upcoming new version releases (he said it might took about month).
Temporarly I know how to handle this (add code and recompile java files), I already tested it and its work great. All events now working. If you really need that support now and don't want to wait, I can share how to do that.
Cheers
Yes. I would like to see your solution because I am able to navigate using the D-pad but I couldn't see which element I am navigating to. I need to highlight or show focus on the element that I navigating to.
Having console.log inside the TVEventHandler callback seems to break it when running without remote js debugger on.
I have observed that D-pad does not work if there is no focusable component. To solve this, I have placed a transparent touchable opacity component on my screen. After that D-pad started working. My code for D-pad key event is given below:
enableTVEventHandler() {
this.tvEventHandler = new TVEventHandler();
this.tvEventHandler.enable(this, (cmp, { eventType, eventKeyAction }) => {
// eventKeyAction is an integer value representing button press(key down) and release(key up). "key up" is 1, "key down" is 0.
if (eventType === 'playPause' && eventKeyAction === 0)
{
console.log('play pressed')
}
else if(eventType === 'fastForward' && eventKeyAction === 0){
console.log('forward pressed')
}
else if (eventType === 'rewind' && eventKeyAction === 0){
console.log('rewind pressed')
}
else if (eventType === 'select' && eventKeyAction === 0)
{
console.log('select pressed')
}else if(eventType === 'left' && eventKeyAction === 0){
console.log('left pressed')
}
else if(eventType === 'right' && eventKeyAction === 0){
console.log('right pressed')
}
else if(eventType === 'up' && eventKeyAction === 0){
console.log('up pressed')
}
else if(eventType === 'down' && eventKeyAction === 0){
console.log('down pressed')
}
});
}
I am implementing the drag and drop mechanic using react-dnd library, but I find it hard to style my drop targets. I want to show the user which drop target is available to drop on, but using the isOver and canDrop will only style the item that is currently being hovered on.
If I use the !isOver value, all the divs are being styled, without even dragging any of the elements.
How can I style the drop targets only when the dragging of an element happens?
This is my code so far, for a #DropTarget:
import React from 'react';
import {DropTarget} from 'react-dnd';
import {ItemTypes} from './Constants';
const target = {
drop(props, monitor, component){
// console.log("Dropped on", props.id);
},
canDrop(props, monitor, component){
var cardColumn = monitor.getItem().column;
var targetColumn = props.column;
return false; // still testing styling when only an element is being dragged on the page
}
};
#DropTarget(ItemTypes.CARD, target, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver({shallow: true}),
canDrop: monitor.canDrop(),
}))
class CardList extends React.Component{
constructor(props){
super(props);
this.addClass = this.addClass.bind(this);
}
addClass(){
const {isOver, canDrop} = this.props;
if(isOver && canDrop){
return "willDrop"; // green background for .card-list
}
if(isOver && !canDrop){
return "noDrop"; // red background for .card-list
}
if(!isOver && !canDrop){
return ""; // will style all the backgrounds in a color, but not when dragging
}
}
render(){
const {connectDropTarget} = this.props;
return connectDropTarget(
<div class={"card-list col-xl-12 col-lg-12 col-md-12 col-sm-12 col-xs-12 " + this.addClass()} id={this.props.id}>
{this.props.children}
</div>
);
}
}
export default CardList;
Is there a way to get the isDragging value when an element is being dragged on the page, since this is the only possibility to obtain what I want.
Thanks!
Both isOver and canDrop implicitly do the isDragging check, per http://react-dnd.github.io/react-dnd/docs-drop-target-monitor.html - note that they only return true if a drag operation is in progress. Therefore, if you want to style drop targets such that only when something that can be dragged is being dragged, then I think you need another case in your addClass() function to handle that, like this:
addClass(){
const {isOver, canDrop} = this.props;
if(isOver && canDrop){
return "willDrop"; // green background for .card-list
}
if(isOver && !canDrop){
return "noDrop"; // red background for .card-list
}
if(!isOver && canDrop){
return ""; // THIS BLOCK WILL EXECUTE IF SOMETHING IS BEING DRAGGED THAT *COULD* BE DROPPED HERE
}
}
And I don't think you want the !isOver && !canDrop block - this will execute even when nothing is being dragged at all.
I am trying to create a TabBar has preview images of the connected layout's children. However after adding several tabs (the exact number depends on the number of elements within the tabs) QML throws an error and the PreviewTabBar loses all its content children.
The following is a minimal working example:
My main.qml:
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.3
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
StackLayout {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
}
Timer {
interval: 50; running: true; repeat: true
onTriggered: addTab()
}
function addTab() {
console.log("add Tab")
var component = Qt.createComponent("qrc:/TabContent.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
var item = component.createObject(swipeView)
tabBar.addTab(item)
tabBar.currentIndex = tabBar.contentChildren.length - 1
console.log("current index " + tabBar.currentIndex)
}
header: PreviewTabBar {
id: tabBar
currentIndex: swipeView.currentIndex
}
}
The PreviewTabBar.qml containing previews of the content:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabBar {
signal closeCurrentTab
clip: true
background: Rectangle {
color: "white"
}
function addTab(imageSource) {
var component = Qt.createComponent("PreviewTabButton.qml")
if(component.status !== Component.Ready)
console.log("component not ready")
else {
var item = component.createObject()
item.setSource(imageSource)
addItem(item)
}
}
function closeTab() {
console.log("closeTab")
closeCurrentTab()
}
}
and last but not least the PreviewButton.qml using a ShaderEffectSource to render the preview:
import QtQuick 2.8
import QtQuick.Controls 2.1
TabButton {
height: 80
width: 140
function setSource(source) {
preview.sourceItem = source
}
contentItem: ShaderEffectSource {
id: preview
}
}
This example gets to about 80 tabs on my machine, after that the PreviewTabBar loses all its children (not so the StackLayout). However in the real life example with more complicated tab contents I only get up to around 8 tabs. What could I be doing wrong?
Here is the relevant part of the application output:
qml: current index 99
qml: add Tab
file:///usr/lib/qt/qml/QtQuick/Controls.2/TabButton.qml:65: TypeError: Cannot read property of null
qml: current index 100
qml: add Tab
qml: current index 1
I tried finishing the dynamic component creation in a callback as described here:
http://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html#creating-a-component-dynamically
however that brough no improvement.
Here is a link to the example project:
https://www.file-upload.net/download-12341284/tabtestshader.zip.html
The most probable cause is line 17 in PreviewTabBar.qml which reads:
var item = component.createObject()
As you have no parent set in the createObject()-function the GarbageCollector tends to run wild, and delete your object, even if it is still referenced.
Though not documented that way, you should always pass a parent object, to make sure it survives the GC.
A more stable way would be to generate the Tabs from a model, and add the according model entries in the addTab-functions.
As a little remark on the side: You create a new component everytime you call one of your addTab-functions. Why don't you declare it once like
Component {
id: myComp1
...
}
and create the objects from that?
I've found fantastic topic on creation of Qt/QML implementation of Android Toast. I am trying to upgrade it after Toast disappears some signal is emmited - I want to quit simple Qt/QML app. Here is ToastManager:
import QtQuick 2.7
Column
{
id: root
z: Infinity
spacing: 5
anchors.centerIn: parent
signal signalQuitApp;
property var toastComponent
function show(text,
duration)
{
var toast=toastComponent.createObject(root);
toast.selfDestroying=true;
toast.show(text,
duration);
signalQuitApp();
} // show
Component.onCompleted:
{
toastComponent=Qt.createComponent("Toast.qml");
} // Component.onCompleted
} // Column
The result is, if I click some button inside QML application, it quits before Toast animation is over. How do I emit signal AFTER Toast dissapears?
Assuming you are referring to the answer by #ayberk-Özgür you will need to modify Toast.qml to emit the signal when it is done.
id: root
signal toastFinished()
// ...
onRunningChanged:{
if (!running) {
root.toastFinished();
if (selftDestroying)
root.destroy();
}
}
Before you show the toast you connect to that signal
toast.toastFinished.connect(Qt.quit);
toast.show(text, duration);