SwiftUI Menu main "Button" view with changing text - button

I am using a menu and the view I have for the main button has text inside it which can change. It's between 4 and 6 characters.
When the text changes, the button animates left and right and the text animates in (which is not what I want) ..
I'd ideally like to use a buttonStyle but this doesn't seem possible.
Any ideas how I can keep the button static ? The right button is a "real" button which behaves.
Menu {
if fuelTypeisAvailable(fuelType: "Gazole") {
Button {
updateStuff()
Haptics.shared.play(.light)
preferredFuelType = "Gazole"
} label: {
Label("Gazole €\(closestGazole ?? "")", systemImage: isPreferedFuelType(type: "Gazole"))
}
}
etc
label: {
// This is the left blue button
Text("\(preferredFuelType)")
.padding(25)
.font(.system(size: 20, weight: .light, design: .default))
.foregroundColor(.primary)
.background(
Circle()
.fill(.blue).opacity(leftButtonIsHidden ? 0 : 0.8)
)
}

Here is a working version that fixes the animation issues. It even accepts the buttonStyle.
label: {
// This is the left blue button
ZStack{
Circle().fill(.blue).opacity(0.8)
Text("\(preferredFuelType)")
.font(.system(size: 22, weight: .light, design: .default))
.foregroundColor(.primary)
.animation(nil)
}.frame(width: 80, height: 80)
}
.buttonStyle(TwitterButtonStyle())

Related

QML StackView : Changing replaceEnter/Exit animation dynamically

Is there anyway to change the replaceEnter/Exit Transition animation dynamically depending on the next QML file to be loaded in the stack view.
Situation:
I have a Centre QML file having 4 buttons on the 4 sides of the screen. There are other 4 QML files namely Top, Bottm, Right and Left. On press of top button on the Centre QML the Top qml file should transitioned from top-to-bottom and replace the centre one. Similarly on press of left button on the centre QML the left QML should enter there display area from left to right and replace the centre one.
I tried using replaceEnter/Exit property. But not able to understand how to change it dynamically depending on the next QML to be displayed.
take a look at the doc for infos about customizing transitions for Stackview.
If you need more than one transition you can define them separately and then assign them just before they are used. Here is an example:
StackView {
id: control
pushEnter: topTransition
Transition {
id: topTransition
XAnimator {
from: (control.mirrored ? -1 : 1) * -control.width
to: 0
duration: 400
easing.type: Easing.OutCubic
}
}
Transition {
id: bottomTransition
XAnimator {
from: 0
to: (control.mirrored ? -1 : 1) * control.width
duration: 400
easing.type: Easing.OutCubic
}
}
Button {
text: "Push page from bottom"
onClicked: {
control.pushEnter = bottomTransition
control.push(bottomPage)
}
}
}
You will have to explicitly set all push/pop/replace transitions you need before each button click.

GeometryReader not generating correct screen height?

public var body: some View
{
ZStack{
GeometryReader { geometry in
RoundedRectangle(cornerRadius: 25, style: .continuous)
.frame(width: geometry.size.width*1.00, height: geometry.size.height*1.00)
.zIndex(0)
}
}
}
I'm using GeometryReader to draw a rounded rectangle to fill up the entire watch screen, this looks fine on a 38mm watch simulator, but as I increase the watch size to 40, 42, 44mm I noticed that the height is not filling up the whole screen. I have to adjust my multiple to say 1.1 for example to fill up more of the screen.
Can someone tell me if I am using GeometryReader incorrectly?
Unless you really need the full functionality of the geometry reader, to actually measure the size of the object of the screen, then I think you could achieve the effect you want by setting the frame's maxWidth and maxHeight to .infinity and by ignoring the safe area on the bottom.
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.edgesIgnoringSafeArea(.bottom)
}
}
Note that when you use a ZStack the order of the items in it determine the order on the screen. The first item in the stack will be at the bottom, and then each item will be layered on top.

Adding shadow on view breaks focusable buttons within it

When I add shadow on a view that contains a button then the button will no longer be clickable. The same code on iOS works as expected, but on tvOS it breaks the button. Am I doing something wrong here? Is there a workaround?
Here is my code,
VStack {
Button(action: {
print("Button clicked") // This is never called
}) {
Text("test")
}
.padding()
}
.background(Color.red)
.shadow(color: Color.black, radius: 14, x: 0, y: 4)
I found a workaround for this issue, since backgrounds can be set to any view you can apply all the styling you need to the background, and it won't break the buttons within the view.
.background(RoundedRectangle(cornerRadius: 8)
.fill(Color.red)
.shadow(color: Color.black, radius: 14, x: 0, y: 4))

ExtJS 4 button next

Problem is probably simple but I can't find the proper answer.
I have a panel with only four buttons. Just vbox with buttons. And now I want to select and press this buttons not only with mouse click but also via keyboard. So I used Ext.KeyMap and I catch every key I want to: ENTER, TAB, DOWN and UP. But I can't find simple way to move focus betveen this buttons.
E.g. I'm focused on first button, press DOWN key and I want to be focused on the second button. No way. I tried
but1.down('button[action=next]').focus(false, 100))
but it can't work. Be so kind as to prompt please.
Well what can I say, just VERY BIG thank you – it is working obviously.
I had no idea to use KeyNav.
But it’s working in such a simple example My case is a little bit more complicated and I asked this question just simplified my situation. So this menu is the second screen in my application and it is constructed in such a way:
PANEL
Panel1
Label1
Button 1
Button 2
Button 3
Panel2
Label2
Button 4
Button 5
Panel3
Label3
Button 6
Button 7
Button 8
and every user can see (panels are hidden on the start) and use parts of this structure (e.g. Panel1, 3 and Button 8). I decide about it one step before (login step) and I show to the user menu only for him in the container defined:
Ext.define('Gromel.view.Menu', {
extend: 'Ext.container.Container',
requires:[
'Ext.tab.Panel',
'Ext.layout.container.Border',
'Ext.form.Label',
'Ext.form.Panel'
],
xtype: 'app-menu',
fullscreen: true,
layout: 'fit',
...
I place your code on the PANEL level and it's working almost properly. And I use the following default definition for above items:
defaults: {
margin: '0 0 10 0',
baseCls: 'x-btn-default-large',
cls: 'cap-btn',
style: 'font-size:18px;text-align: center',
height: 40,
width: '50%',
// yours:
handler: function () {
this.up('panel').activeButton = this.activeIndex;
}
}
so I modified your cls change method to:
button[method]('x-focus x-btn-focus x-btn-default-large-focus')
and your procedure is working.
Problems I can't manage now are:
as you see on the same level as buttons I have labels and I don't know how to bypass them;
more important - I want to run this procedure only on menu panel not in login panel and the rest (deeper in my structure) but this is global, so if I press ENTER on login panel I see the effect on next, menu panel; I replaced ENTER effect in the following way (I want to press ENTER on every button in menu and run different presses events):
case e.ENTER: butt.fireEvent('click', butt); break;
So if it isn’t to much for you be so kind and prompt me more please.
Try to use ExtJS KeyNav.
KeyNav provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind navigation keys to function calls that will get called when the keys are pressed, providing an easy way to implement custom navigation schemes for any UI component.
As you said
I have a panel with only four buttons.
I have work around that, I have created an small sencha fiddle demo. It will show you how is working. I hope this will help you to solve your problem.
You can also refer this Key Navigation Sample
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
title: 'Button Example with keyNav',
margin: 10,
bodyStyle: {
'border-width': '2px'
},
layout: {
type: 'vbox',
align: 'center'
},
defaults: {
xtype: 'button',
height: 50,
width: '70%',
margin: '20 0',
handler: function () {
this.up('panel').activeButton = this.activeIndex;
}
},
items: [{
text: 'My button 1',
activeIndex: 0
}, {
text: 'My button 2',
activeIndex: 1
}, {
text: 'My button 3',
activeIndex: 2
}, {
text: 'My button 4',
activeIndex: 3
}],
listeners: {
afterrender: function () {
var panel = this;
panel.keynav = Ext.create('Ext.util.KeyNav', {
target: Ext.getBody(),
scope: panel,
up: panel.doFocusOnButton,
down: panel.doFocusOnButton,
enter: panel.doFocusOnButton,
tab: panel.doFocusOnButton
});
//Remove cls on panel click
panel.el.on('click', function () {
this.doAddRemoveCls('removeCls');
}, panel)
panel.focus();
}
},
/*
* Common event will fire on key : ENTER, TAB, UP, DOWN
* #param {Ext.EventObject} e Just as Ext.Element wraps around a native DOM node
*/
doFocusOnButton: function (e) { //{ http://docs.sencha.com/extjs/4.2.5/#!/api/Ext.EventObject }
var panel = this,
button = '',
totalItem = panel.items.length - 1;
if (Ext.isDefined(panel.activeButton) == false) {
panel.activeButton = 0;
} else {
this.doAddRemoveCls('removeCls');
switch (e.getKey()) {
case e.ENTER:
case e.DOWN:
case e.TAB:
panel.activeButton++;
if (panel.activeButton > totalItem) {
panel.activeButton = 0;
}
break;
case e.UP:
panel.activeButton--;
if (panel.activeButton < 0) {
panel.activeButton = totalItem;
}
break;
}
}
this.doAddRemoveCls('addCls');
},
//This function will add or remove cls..
doAddRemoveCls: function (method) {
var panel = this,
index = panel.activeButton,
button = Ext.isDefined(index) ? panel.down('[activeIndex=' + index + ']') : null;
if (button) {
button[method]('x-focus x-btn-focus x-btn-default-small-focus')
}
}
});

QML Changing style of TextField's menu

I would like to customize style of my application and I'm stuck on the style of TextField pop-up menu.
TextField.style allows to customize the look of TextField but it doesn't contain the style of the menu. According to documentation there is a property menu containing the Menu so I tried something like this:
TextField {
menu.style: MenuStyle {
//...
}
}
Code above complains that property style is non-existent so it's not exactly Menu, it's Component used to create the menu and I don't know if there is a way to get through it to the actual Menu. Documentation only mentions that TextField.menu can be set to null to disable it completely and doesn't provide other use cases.
So is there a way to get to the menu of TextField and change its style?
Well, you should post all relevant code here. Anyway, you cannot define the TextField menu and its style separately. See the example below to customize Menu style and adding it to the TextField inline:
TextField {
text: "text here"
anchors.centerIn: parent
menu: Menu {
style: MenuStyle {
frame: Rectangle {
color: "green"
border.color: "purple"
}
itemDelegate {
background: Rectangle {
color: "yellow"
}
label: Text {
color: styleData.selected ? "red" : "blue"
text: styleData.text
}
}
}
MenuItem { text: "Cut" }
MenuItem { text: "Copy" }
}
}
See this page for complete list of MenuStyle properties.

Resources