How do I create a button with a background colour of my choice in blackberry 10 cascades? - blackberry-10

I want to create a button with a background colour of my choice in blackberry 10 cascades.
How can i do this ?

It's quite simple to create your own buttons, once you get used to qml at least :)
Below is an example of a custom button, place it in a file such as CustomButton.qml. You could also use a property to be able to pass through a colour making it easily reusable.
Container {
property alias text: label.text
signal clicked() //emits a clicked signal.
gestureHandlers: [
TapHandler {
onTapped: {
clicked();
}
}
]
layout: DockLayout {
}
Container {
background: Color.Red
horizontalAlignment: HorizontalAlignment.Fill
Container {
horizontalAlignment: HorizontalAlignment.Center
verticalAlignment: VerticalAlignment.Center
topPadding: 10
bottomPadding: 15
leftPadding: 20
rightPadding: 20
Label {
id: label
text: "demo"
textStyle {
base: tsLabel.style
}
topMargin: 0
bottomMargin: 0
topPadding: 0
bottomPadding: 0
}
}
}
attachedObjects: [
TextStyleDefinition {
id: tsLabel
base: SystemDefaults.TextStyles.BodyText
fontSize: FontSize.Small
color: Color.White
fontWeight: FontWeight.W100
}
]
}
To use this in your main page you would just do the following:
CustomButton {
text: "my button"
onClicked: {
//do code
}
}
To enhance on this you could add an animation or colour change in the onTapped function. You could also use a 9patch for the button image, using imagePaint instead of Color.Red.

Related

SwiftUI center align a view except if another view "pushes" it up

Here is a breakdown.
I have a zstack that contains 2 vstacks.
first vstack has a spacer and an image
second has a text and button.
ZStack {
VStack {
Spacer()
Image("some image")
}
VStack {
Text("press the button")
Button("ok") {
print("you pressed the button")
}
}
}
Now this setup would easily give me an image on the bottom of a zstack, and a centered title and button.
However if for example the device had a small screen or an ipad rotates to landscape. depending on the image size (which is dynamic). The title and button will overlap the image. instead of the button being "pushed" up.
In UIKit this is as simple as centering the button to superview with a high priority and having greaterThanOrEqualTo image.topAnchor with a required priority.
button would be centered in screen but if the top of the image was too big the center constraint would give priority to the image top anchor required constraint and push the button up.
I have looked into custom alignments and can easily get always above image or always center but am missing some insight in having it both depending on layout. Image size is dynamic so no hardcoded sizes.
What am i missing here? how would you solve this simple yet tricky task.
There might be an easier way using .alignmentGuide but I tried to practice on Layout for this answer.
I created a custom ImageAndButtonLayout that should do what you want: it takes two views assuming the first is the image and the second is the button (or anything else).
They are put into subviews just for clarity, you can also put them directly into ImageAndButtonLayout. For testing you can change the height of the image via slider.
The Layout always uses the available full height and pushes the first view (image) to the bottom - so you don't need an extra Spacer() with the image. The position of the second view (button) is calculated based on the height of the first view and the available height.
struct ContentView: View {
#State private var imageHeight = 200.0 // for testing
var body: some View {
VStack {
ImageAndButtonLayout {
imageView
buttonView
}
// changing "image" height for testing
Slider(value: $imageHeight, in: 50...1000)
.padding()
}
}
var imageView: some View {
Color.teal // Image placeholder
.frame(height: imageHeight)
}
var buttonView: some View {
VStack {
Text("press the button")
Button("ok") {
print("you pressed the button")
}
}
}
}
struct ImageAndButtonLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let maxsizes = subviews.map { $0.sizeThatFits(.infinity) }
var totalWidth = maxsizes.max {$0.width < $1.width}?.width ?? 0
totalWidth = min(totalWidth, proposal.width ?? .infinity )
let totalHeight = proposal.height ?? .infinity // always return maximum height
return CGSize(width: totalWidth, height: totalHeight)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let heightImage = subviews.first?.sizeThatFits(.unspecified).height ?? 0
let heightButton = subviews.last?.sizeThatFits(.unspecified).height ?? 0
let maxHeightContent = bounds.height
// place image at bottom, growing upwards
let ptBottom = CGPoint(x: bounds.midX, y: bounds.maxY) // bottom of screen
if let first = subviews.first {
var totalWidth = first.sizeThatFits(.infinity).width
totalWidth = min(totalWidth, proposal.width ?? .infinity )
first.place(at: ptBottom, anchor: .bottom, proposal: .init(width: totalWidth, height: maxHeightContent))
}
// place button at center – or above image
var centerY = bounds.midY
if heightImage > maxHeightContent / 2 - heightButton {
centerY = maxHeightContent - heightImage
centerY = max ( heightButton * 2 , centerY ) // stop at top of screen
}
let ptCenter = CGPoint(x: bounds.midX, y: centerY)
if let last = subviews.last {
last.place(at: ptCenter, anchor: .center, proposal: .unspecified)
}
}
}

SwiftUI: Synchronise 2 Animation Functions (CAMediaTimingFunction and Animation.timingCurve)

I was using CAMediaTimingFunction (for a window) and Animation.timingCurve (for the content) with the same Bézier curve and time to deal with the resizing. However, there can be a very small time difference and therefore it caused the window to flicker irregularly. Just like this (GitHub repository: http://github.com/toto-minai/DVD-Player-Components ; original design by 7ahang):
Red background indicates the whole window, while green background indicates the content. As you can see, the red background is visible at certain points during the animation, which means that the content is sometimes smaller than the window, so it generates extra small spaces and causes unwanted shaking.
In AppDelegate.swift, I used a custom NSWindow class for the main window and overrode setContentSize():
class AnimatableWindow: NSWindow {
var savedSize: CGSize = .zero
override func setContentSize(_ size: NSSize) {
if size == savedSize { return }
savedSize = size
NSAnimationContext.runAnimationGroup { context in
context.timingFunction = CAMediaTimingFunction(controlPoints: 0, 0, 0.58, 1.00) // Custom Bézier curve
context.duration = animationTime // Custom animation time
animator().setFrame(NSRect(origin: frame.origin, size: size), display: true, animate: true)
}
}
}
In ContentView.swift, the main structure (simplified):
struct ContentView: View {
#State private var showsDrawer: Bool = false
var body: some View {
HStack {
SecondaryAdjusters() // Left panel
HStack {
Drawer() // Size-changing panel
.frame(width: showsDrawer ? 175 : 0, alignment: .trailing)
DrawerBar() // Right bar
.onTapGesture {
withAnimation(Animation.timingCurve(0, 0, 0.58, 1.00, duration: animationTime)) { // The same Bézier curve and animation time
showsDrawer.toggle()
}
}
}
}
}
}
The animated object is the size-changing Drawer() in the middle. I suppose that it is because the different frame rate of two methods. I'm wondering how to synchronise the two functions, and whether there's another way to implement drawer-like View in SwiftUI. You could clone the repository here. Thanks for your patient.

How to fix the font that cut from the bottom in UIKit?

I have a custom font in the app and I have applied it on the Signup button and it has following result:
As you can see the 'g' has been cut from the bottom. The view is a UIButton with image on it and following properties:
Custom font of size 22.7
View Semantic: Force Right-to-Left
Content Insets: Left:44.3, Right:24.7, Top:22 and Bottom:22
Image Insets: Left only:11.7
I have tried to fix it by providing baselineOffset to value 1 in following code:
#IBDesignable extension UIButton {
#IBInspectable var baselineOffset: CGFloat {
set {
let attributedString = NSMutableAttributedString(string: title)
attributedString.addAttribute(NSAttributedString.Key.baselineOffset, value: newValue, range: NSMakeRange(0, title.count))
self.setAttributedTitle(attributedString, for: .normal)
}
get { 0 }
}
var title: String {
get { self.title(for: .normal) ?? "" }
}
}
It fix the bottom cut but now the title cuts from the top.
Is there any way to add extra space for a title text to draw on the screen?

SwiftUI white space under the NavigationBar

I have a view with a NavigationBar with a large title and content inside. I've changed the content background color and the NavigationBar background color.
var body: some View {
NavigationView {
VStack {
//content
}.background(Color.green)
.edgesIgnoringSafeArea(.bottom) //to fill the white space at the bottom
.navigationBarTitle("Wallets")
}
}
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
let standartAppearance = UINavigationBarAppearance()
standartAppearance.backgroundColor = UIColor.green
navigationBar.standardAppearance = standartAppearance
navigationBar.scrollEdgeAppearance = standartAppearance
navigationBar.compactAppearance = standartAppearance
}
}
And now if I move to the next view using the NavigationLink, and this view has a title with .inline display mode (different NavigationBar size), in the moment of the transition I see the white space under the first Navigation bar. I can fill it if I make .edgesIgnoringSafeArea(.all) for my VStack, but in this case all my content jump under the NavigationBar. How can I color the space under the NavigationBar to custom color?
Looks like it's a bug. I didn't find the normal solution. Here is a workaround:
We should calculate the NavigationBar heigh and fill the space behind it.
var deviceHeight: CGFloat {
UIScreen.main.bounds.height
}
func calcPadding() -> CGFloat {
var padding: CGFloat = 0.0
switch self.deviceHeight {
case 568.0: padding = 94.0 + 6.0
case 667.0: padding = 96.0 + 10.0
case 736.0: padding = 96.0 + 10.0
case 812.0: padding = 106.0 + 10.0
case 896.0: padding = 106.0 + 10.0
default:
padding = 106.0
}
return padding
}
var body: some View {
NavigationView {
VStack {
VStack {
//content
}
.padding(.top, calcPadding())
.background(Color.myBackground)
}
.background(Color.myBackground)
.edgesIgnoringSafeArea(.all)
}
}

Re-sizing the border in a Image View Blackberry10 cascades

i need to set a image-view it should have the square curve round at the edges ,How to do this can anyone send me some solution to do this
Cascades qml does not support borders or rounded corners. Unless someone has a better solution what I've done is to wrap the imageview in a container and use a 9-slice image for the container background.
A rough example:
Container {
topPadding: 5
leftPadding: 5
rightPadding: 5
bottomPadding: 5
background: mybackground.imagePaint
ImageView {
imageSource: "asset:///images/image1.png"
}
attachedObjects: [
ImagePaintDefinition {
id: mybackground
imageSource: "asset:///images/bgimage.amd"
}
]
}
Adjust the padding as needed for thinner/thicker border.