how to display text in textinput box when i press number button. i am creating passcode login - kivy

I am creating Passcode login app screen when i press button it will print text but not in textinput box. i want to print my text in text box which i created in my first screen. please help me.
kivy
BT0 = Button(text="0", size_hint=(0.1, 0.1), pos_hint={'center_x': 0.5, 'center_y': 0.3}, color=(0, 0, 0, 1))
BT0.bind(on_press=callback)
layout.add_widget(BT0)
textinput = TextInput(password=True,multiline=False, size_hint=(.2, .05), halign="center",
pos_hint={'center_x': 0.5, 'center_y': 0.8})
textinput.bind()
layout.add_widget(textinput)
return layout

From what I understood, you are trying to retrieve the text of a TextInput in another screen. All you have to do is give the TextInput an id, then you can simply grab the text by running self.ids.NAME_OF_ID.text (this must be within a class function)

Related

In iOS 14 how do you tap a button programmatically?

In iOS 14 I have configured a button to display a menu of questions. On its own the button is working perfectly. Here’s how it’s configured:
let button = UIButton()
button.setImage(UIImage(systemName: "chevron.down"), for: .normal)
button.showsMenuAsPrimaryAction = true
button.menu = self.menu
I have it set on a text field’s rightView. This is how it looks when the menu is displayed.
When a menu item is tapped, that question appears in a label just above the text field. It works great. Except….
I also want the menu to appear when the user taps in the text field. I don’t want them to have to tap on the button specifically. In the old days of target-action this was easy: button.sendActions(for: .touchUpInside). I tried that and .menuActionTriggered and .primaryActionTriggered but none of those work. I think sendActions() is looking for the old selector based actions.
But there’s a new sendActions(for: UIControl.Event) method. Here’s what I’m trying in textFieldShouldBeginEditing():
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
let tempAction = UIAction { action in
print("sent action")
}
menuButton.sendAction(tempAction)
print("textField tapped")
return false
}
Sure enough, “sent action” and “textField tapped” appear in the console when the text field is tapped. But I have no idea what UIAction I could send that means “display your menu”. I wish there was this method: send(_: UIControl.Event).
Any ideas on how to get the button to display its menu when the text field is tapped?
ps. yes, textFieldShouldBeginEditing will need to know if a question has been selected and in that case will need to allow editing. That part is easy.
From what I read, you cannot programmatically trigger UIContextMenuInteraction as interactions seem to be handled internally by itself unlike send(_: UIControl.Event)
I see this mentioned on this SO post here
Also in the docs it seems that we don't have access to interaction management Apple needs to decide 3D touch is available or default back to long tap
From the docs
A context menu interaction object tracks Force Touch gestures on devices that support 3D Touch, and long-press gestures on devices that don't support it.
Workaround
I can propose the following workaround for your use case. My example was created using frame instead of auto layout as faster and easier to demo the concept this way, however you will need to make adjustments using autolayout
1. Create the UI elements
// I assume you have a question label, answer text field and drop down button
// Set up should be adjusted in case of autolayout
let questionLabel = UILabel(frame: CGRect(x: 10, y: 100, width: 250, height: 20))
let answerTextField = UITextField(frame: CGRect(x: 10, y: 130, width: 250, height: 50))
let dropDownButton = UIButton()
2. Regular setup of the label and the text view first
// Just regular set up
private func configureQuestionLabel()
{
questionLabel.textColor = .white
view.addSubview(questionLabel)
}
// Just regular set up
private func configureAnswerTextField()
{
let placeholderAttributes = [NSAttributedString.Key.foregroundColor :
UIColor.lightGray]
answerTextField.backgroundColor = .white
answerTextField.attributedPlaceholder = NSAttributedString(string: "Tap to select a question",
attributes: placeholderAttributes)
answerTextField.textColor = .black
view.addSubview(answerTextField)
}
3. Add the button to the text view
// Here we have something interesting
private func configureDropDownButton()
{
// Regular set up
dropDownButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
dropDownButton.showsMenuAsPrimaryAction = true
// 1. Create the menu options
// 2. When an option is selected update the question label
// 3. When an option is selected, update the button frame
// Update button width function explained later
dropDownButton.menu = UIMenu(title: "Select a question", children: [
UIAction(title: "Favorite movie") { [weak self] action in
self?.questionLabel.text = action.title
self?.answerTextField.placeholder = "Add your answer"
self?.answerTextField.text = ""
self?.updateButtonWidthIfRequired()
},
UIAction(title: "Car make") { [weak self] action in
self?.questionLabel.text = action.title
self?.answerTextField.placeholder = "Add your answer"
self?.answerTextField.text = ""
self?.updateButtonWidthIfRequired()
},
])
// I right align the content and set some insets to get some padding from
// the right of the text field
dropDownButton.contentHorizontalAlignment = .right
dropDownButton.contentEdgeInsets = UIEdgeInsets(top: 0.0,
left: 0.0,
bottom: 0.0,
right: 20.0)
// The button initially will stretch across the whole text field hence we
// right aligned the content above
dropDownButton.frame = answerTextField.bounds
answerTextField.addSubview(dropDownButton)
}
// Update the button width if a menu option was selected or not
func updateButtonWidthIfRequired()
{
// Button takes the text field's width if the question isn't selected
if let questionText = questionLabel.text, questionText.isEmpty
{
dropDownButton.frame = answerTextField.bounds
return
}
// Reduce button width to right edge as a question was selected
dropDownButton.frame = CGRect(x: answerTextField.frame.width - 50.0,
y: answerTextField.bounds.origin.y,
width: 50,
height: answerTextField.frame.height)
}
4. End Result
Start with a similar view to yours
Then I tap in the middle of the text field
It displays the menu as intended
After selecting an option, the question shows in the label and the placeholder updates
Now I can start typing my answer using the text field and the button is only active on the right side since it was resized
And the button is still active
Final thoughts
Could be better to put this into a UIView / UITextField subclass
This was an example using frames with random values, adjustments need to made for autolayout
Edits from OP (too long for a comment):
I had tried setting contentEdgeInsets so the button was way over to the left but it covered up the placeholder text.
Your idea of simply adding the button as a subview of the text field was the key, but...
After selecting a question and resizing the button, if the text field was the first responder, tapping the button had no effect. The button was in the view hierarchy but the text field got the tap.
So, when a question is selected, I remove the button from its superview (the textfield) and add it to the textField's rightView. Then it would accept a tap even if the textField was the first responder.
And, as you suspected, I had to pin the button to the textField with constraints.

Any way to stop SwiftUI Text showing an ellipse?

I have a Text view that dynamically shows different text depending on the value of a state variable. As I cycle through the values, if the new text is longer than the old text, I momentarily get an ellipse (...) before the new text is shown. The code that experiences this looks like:
Text(flashModeDescription(flashMode: appSettings.flashMode))
.font(.body).foregroundColor(.white)
.opacity(flashModeDescVisible ? 1: 0)
.animation(.easeIn(duration: 0.25))
The Text view is the last item in an HStack.
This is due to animation defined, so the following could fix
Text(flashModeDescription(flashMode: appSettings.flashMode))
.font(.body).foregroundColor(.white)
.animation(nil) // << here !!
.opacity(flashModeDescVisible ? 1: 0)
.animation(.easeIn(duration: 0.25))
so animation would affect only opacity

how to make text vertically center in fabric js TextBox

I am working on one fabric js editor, in which I need to implement TextBox as a Button look and feel,
For that, I Have implemented TextBox with Background, But Problem is that Height of TextBox.
I am trying this kind of code :
var text = new fabric.Textbox("this is text", {
top: 0,
left: 0,
width: 300,
height: 500,
fill: 'red'
})
canvas.add(text);
Now my Textbox is rendered of width: 300 but height is not rendered. how can I set Height to My TextBox
And another Thing, when I set Height to TextBox, I need to keep text in Center of height (vertical center)
what should I do, I can't understand, how to override default fabtic.Textbox class.
Please help me, If any one have Any suggestion.

Kivy: Swiping (Carousel & ScreenManager)

I have two Screens in a ScreenManager that both contains a number of buttons in a ScrollView. The idea is that one steps forward (right) by clicking a button. And step back (left) by swiping back. So I am trying to add a Carousel to implement that one swipe on the second page. This is what I have tried:
self.root = ScreenManager(id = 'screen_manager')
main_screen = Screen(name = 'main_screen')
scroller = Scroller()
button_text = ['teach', 'move', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8']
for text in button_text:
scroller.view.add_widget(Field(name=text, direction='left', current='teach'))
main_screen.add_widget(scroller)
self.root.add_widget(main_screen)
carousel = Carousel(direction='left', id='carousel')
teach = Screen(name = 'teach')
scroller2 = Scroller()
button_text = ['vocab', 'drills']
for text in button_text:
scroller2.view.add_widget(Field(name=text, direction='right', current='main_screen'))
carousel.add_widget(scroller2)
teach.add_widget(carousel)
self.root.add_widget(teach)
But since I have only added the second Screen, it's not possible to swipe in either direction. Carousel's load_slide() method takes a slide as argument. Assuming by slide they mean a Carousel. Given I am going to have a lot pages, I probably need the Carousel to be loaded dynamically, using add_widget() and remove_widget(). Would appreciate some pointers.
Working example of the code I have so far: http://dpaste.com/33464R2
You can do this by using ScreenManager and Gestures. (../kivy/examples/gestures/)
See here kivy-github-gestures
I have explained everything in the code in comments.
First you need create a new Python file named gesture_box.py.
gesture_strings copy from here
from kivy.gesture import GestureDatabase
from kivy.uix.boxlayout import BoxLayout
from kivy.gesture import Gesture
[Paste gesture_strings here]
#This database can compare gestures the user makes to its stored gestures
#and tell us if the user input matches any of them.
gestures = GestureDatabase()
for name, gesture_string in gesture_strings.items():
gesture = gestures.str_to_gesture(gesture_string)
gesture.name = name
gestures.add_gesture(gesture)
class GestureBox(BoxLayout):
def __init__(self, **kwargs):
for name in gesture_strings:
self.register_event_type('on_{}'.format(name))
super(GestureBox, self).__init__(**kwargs)
def on_left_to_right_line(self):
pass
#To recognize a gesture, you’ll need to start recording each individual event in the
#touch_down handler, add the data points for each call to touch_move , and then do the
#gesture calculations when all data points have been received in the touch_up handler.
def on_touch_down(self, touch):
#create an user defined variable and add the touch coordinates
touch.ud['gesture_path'] = [(touch.x, touch.y)]
super(GestureBox, self).on_touch_down(touch)
def on_touch_move(self, touch):
touch.ud['gesture_path'].append((touch.x, touch.y))
super(GestureBox, self).on_touch_move(touch)
def on_touch_up(self, touch):
if 'gesture_path' in touch.ud:
#create a gesture object
gesture = Gesture()
#add the movement coordinates
gesture.add_stroke(touch.ud['gesture_path'])
#normalize so thwu willtolerate size variations
gesture.normalize()
#minscore to be attained for a match to be true
match = gestures.find(gesture, minscore=0.3)
if match:
print("{} happened".format(match[1].name))
self.dispatch('on_{}'.format(match[1].name))
super(GestureBox, self).on_touch_up(touch)
Now create your main.py file.
import gesture_box as gesture
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class Runner(gesture.GestureBox):
pass
class MainApp(App):
def build(self):
return Runner()
if __name__ == '__main__':
app = MainApp()
app.run()
And your main.kv file
<Runner>:
#Handling the gesture event.
on_left_to_right_line: manager.current = 'main_screen'; manager.transition.direction = 'right'
ScreenManager:
id: manager
Screen:
name: "main_screen"
BoxLayout:
orientation: 'vertical'
Label:
Button:
text: "Child 1"
on_release:
manager.current = "child1"
manager.transition.direction = 'left'
Label:
Button:
text: "Child 2"
on_release:
manager.current = "child1"
manager.transition.direction = 'left'
Label:
Screen:
name: "child1"
Label:
text: "Swipe from left to right to go to main screen (CHILD 1)"
Screen:
name: "child2"
Label:
text: "Swipe from left to right to go to main screen (CHILD 1)"
EDIT: Many people have asked me that how these gesture string are generated.
Kivy guys provide this in their examples.
see here https://github.com/kivy/kivy/blob/master/examples/gestures/gesture_board.py
run this file.
python gesture_board.py
It should open a blank window.
make a gesture on it using mouse or touch.
When the on_touch_up event is triggered, It will output the gesture string in the terminal.
for example the output for right_to_left_line would be. this
('gesture representation:', 'eNq1WMtSHEcQvM+PiIs36t3dP4CujuADHFhsACEZNmBlW3/vnOrZxyCWmYPFQQu5OdlVldXVPbp6/Pr494/N/fZ1//1lO3yePnc0XN3teLj59HT71/bTsBP8ig8dXm8+ve5fnr9uX/GnDVffdj5cvStyk7RhF6NUwfO758en/fhYHR9rFx77fWQNO+4RjCH8wCMsw/VvtCFhZWuspJXZfQzn3/FrHa5pE6WIca0NH00agv3z9uNFLBfx4f6i/v0krRKspZE7PnyFdKbNZYU0mykjZo3mXlZI15Ruy9Lu4ZWKSiFi9bIoLVl14RXSHI3xHQuLqyxHLZLS+iuk00ZZYaMFmqOYYAEn5hUFSRtlhY0mptZQ6mJsXpeV00Vp/7+ypom6wkQ0dEGRpXqgtW250pom6goT1biQRWth0Ddflk4T9cxErkSNpTRG3vVcm4TUpVR2GMoUy+Jpo57ZyFZI1aCOddjbSV0CO9FRkohCpdQVoaeV2n6NuqWddmYntWIW4UwmCvtO4oLODlPn0qyYy7J4GmpnhhKer7W0VkngXZSjOjdz9EtwiBf3FZ1o6amdeYrKQJdEGmae1ob9dZQPTEGBtw0UjMIV8umqTa6mehXEJVVauHLBpDyqq1NDsZpiZUeSy+rpqrWTulqphuHfEGr4eL4cxJmbSyiaEt5ili+Ke5rqfBLHucKKbega3BqdxOlNx7Rl8TTV9SQeCFwCa3hg59ip6KRNMGSDYLhSkxWRp6fua8Q5qFoNDC/sVCq8LJ6OelkU76MHuhHaGrQxJJa73dNSb6vkrWrBNrJWYSm226J6pKdx8pSxU4nMEaIX8jPtWsmKRuAfzMm2bGmkpXGyFIeXoZmrEKaukcpJnXGhaAptw4hwXZ4wkZaGrxJHw1QMN6/NcBtaUZW0NMoqcVyCzDB9WA0jhpYdjXQ02nLNhfAnYEyBEAzmRemSdhZe0yzYobhnRcMSaEpaHi4l/Sy6uP9HcVw+MXQKegYt4ysiTz+LL8/FUb1h7uJ72KoYYHkHGC/5X16226fjlb3EeGcvZbi6xiStGxqug6E87HelDreJ2gxtHTU5Ryt1VGYKlTtKM4UqiSLoGaodtbmCdZTnXE+UY64bHaWYoSVR8rlC5oazcAZmam3ObJkZfNu085+RYJ2QSWKM96dqBzPHSl1fJmamiNteBydmZoiZkaBOzEywUI9EwTz74ZGQucYkZVOomWpYlzJ+EzEImXUP/H1CVsDrpNCDwc5LdOqOI5p54x4/RzNx5zdoZo53tzmaqeNSMEczd3OfR2fDlNlIyeztsHSd0EzfpqWdfioaU+ZvRJcZWQCtlzU4i6HlsgZnYXRqiHcZ0hkfaGTB1D5gZPFUP2BkIVXmVeKsnR564IBm7XTaOkc06yXTLjmiWSOpc1SoozRHsxYyVevgn2T+uDHP0cxZfN4kknmKzVtSvKPz1pHMTdTmaOnom3Yv55SeqLQPKD1rKe9Qft5ImHmd7ivpvU7joDj/0Uv0XkChlfReWa4r6b3kl8cEzoTOoMuMbsW01aYBxdqH8WEOHNB+0Eyt8860w90kGSUuMqwfQNOJMI1RvF8m6jFH+wE0bb8j2g+g6fw5oqhFPzgfto/3D/vx/6Tw3nNtbzYctiM4/zze7R+SEsN4ao0rAN4/f9u+3D592eZXJd8sRnw65f/YvTzfff/StetwrRu8huCVAFT0PS484+V98x/WYONd')
('cross:', -1.2199187170964643)
('check:', -2.052277818300959)
('circle:', 0.4973932910874005)
('square:', 0.2907537534396739)
That's it, you have your string :D
I have another method that can be used. It is not through Carousel but it allows you to change screen through swiping. You can create a method that takes in the x point of your initial contact point of the screen and the x point of your final contact of the screen and subtract them. Here is the link to the video(https://www.youtube.com/watch?v=8pqtMAUEUyo&t=65s)
def on_touch_move(self, touch):
if touch.ox - touch.x > 50: # check for swiping gestures
# ScreenManger change screen
touch.ox is the initial contact point of the screen(x axis) and touch.x is the final. If the difference is then greater than a set value it changes screen.
As you asked in your comment.
I have bunch of pages. Each page will have a bunch of buttons. Some
pages have more buttons than can fit on the screen, so they need to be
scrollable.
Now, Scrollable part, you already figured out.(You can do it in kivy file also), See here. And you can easily add that in the code below.
Clicking on a button should take you to the next child
screen (with a scroll effect). On any child it should be possible to
go back to it's parent by swiping back.
Here(Code below) you can both swipe or click on buttons to navigate.
Now,
Given I am going to have a lot pages, I probably need the Carousel to
be loaded dynamically, using add_widget() and remove_widget().
These examples will help you.
Kivy-Showcase and Container
In kivy-showcase have a look at load_screen method and also the build function
Here is an example to add_widgets on click of a button
Builder.load_string('''
[SideBar#BoxLayout]:
content: content
orientation: 'vertical'
size_hint: .2,1
BoxLayout:
orientation: 'vertical'
# just add a id that can be accessed later on
id: content
<Root>:
Button:
center_x: root.center_x
text: 'press to add_widgets'
size_hint: .2, .2
on_press:
sb.content.clear_widgets()
root.load_content(sb.content)
SideBar:
id: sb
''')
class Root(BoxLayout):
def load_content(self, content):
for but in range(20):
content.add_widget(Button(text=str(but)))
class MyApp(App):
def build(self):
return Root()
if __name__ == '__main__':
MyApp().run()
Here is the example for screens.
Here is main.py file
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
class ShowTime(BoxLayout):
carousel = ObjectProperty(None)
class Screen1(Screen):
pass
class Screen2(Screen):
pass
class MainApp(App):
def build(self):
return ShowTime()
if __name__ == '__main__':
MainApp().run()
Here is the main.kv file
<Screen1>:
name: "screen1"
BoxLayout:
orientation: 'vertical'
padding: 50
spacing: 50
Button:
text: "Next (2)"
on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_next()
Button:
text: "Go back (2)"
on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()
<Screen2>:
name: "screen2"
BoxLayout:
orientation: 'vertical'
padding: 100
spacing: 100
Button:
text: "go back (3)"
on_release: self.parent.parent.parent.parent.parent.ids.carousel.load_previous()
<Showtime>:
carousel: carousel
Carousel:
id: carousel
loop: True
BoxLayout:
padding: 100
spacing: 100
Button:
text: 'Tap me or Swipe (1)'
on_release: carousel.load_next()
Screen1:
Screen2:
EDIT 1:
Q- How to use load_slide() method?
load_slide() method takes slides as its parameter def load_slide(self, slide):
Q- So now how to get slide?.
slide is a list property slides = ListProperty([]),
Print this where button has text "go back (3)"
on_release: print( self.parent.parent.parent.parent.parent.ids.carousel.slides)
you will get a list of all slides under id(carousel).
This is how you use it.
.....ids.carousel.load_slide(....ids.carousel..slides[2])

iOS custom UIView as input keyboard [duplicate]

This question already has answers here:
How to create a custom keyboard
(5 answers)
Closed 6 years ago.
I have huge issues when trying to use a custom view as a input keyboard for a text field.
The setup is pretty simple (for testing) : I have a UIView with one button, half the size of the screen and a text field somewhere above it.
I set up a dummy view to be the input view of the text field like so let dummyView : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
Also I added the following setting on viewDidAppear testView.frame.origin.y = view.bounds.height. This is of course ignored as the view appears on screen (putting it on viewDidLoad leads to same behaviour). However, putting it in viewdidLayoutSubviews leads to a very strange behaviour, the view does not appear on screen, but trying to animate to, let's say a 380 origin.y does nothing.
The best part is yet to come: if I hide the view, then the slide up animation (code bellow)
UIView.animateWithDuration(0.6, animations: {
self.testView.frame = self.whereToBe!
}, completion: {
finished in
if finished {
}
})
works just fine. However, trying to slide it down again and resigningFirstResponder on the text field on button press (code bellow)
UIView.animateWithDuration(0.6, animations: {
//self.testView.frame = self.whereToBe!
self.testView.frame.origin.y = self.view.frame.height
}, completion: {
finished in
if finished {
self.view.endEditing(true)
//self.inputField.resignFirstResponder()
self.testView.hidden = true
}
})
shows a fascinating wrong behaviour: the view slides from top to its current position. However, on second press on the button, it works just fine, it slides down BUT it reappears on screen after the animation has completed.
Can you please help me?
Use the view as the inputView of the textfield by simply setting
self.textField.inputView = self.pickerView;
and avoid all these custom animations.

Resources