This is probably a really simple question but I can't seem to find anything in the APIs or across any search engine.
I have a Segmented control that i have set to momentary as a user will select a couple of makes of a car that they want to search for. The issue that I'm running into is that I can't seem to figure out how to recognize which segment was selected. In regular mode its a simple SelectedSegment = index but with momentary its my understanding that the selected segment is always -1 as none are ever "selected"
I have a handler for ValueChanged but I can't figure out what I'm checking for or what I should be sending to determine which segment was selected. Any help would be greatly appreciated. I'm using monotouch but Obj-C would be fine as well.
Thanks!
In your handler, you should check the selectedSegmentIndex to determine which segment was selected:
- (void)valueChanged:(UISegmentedControl *) control {
switch([control selectedSegmentIndex]) {
case 0:
//...
break;
case 1:
//...
break;
}
}
Related
What's the easiest way to have an NSTextField with a "recommendation list" dynamically shown below it as the user types? Just like Safari's address bar that has a menu of some sorts (I'm pretty confident Safari's address bar suggestions is menu since it has rounded corners, blue gradient selection, and background blurring).
I've tried using NSTextView's autocompletion facility but found it was inadequate:
It tries to complete words instead of the whole text fields – in other words, selecting an autocomplete suggestion will only replace the current word.
It nudges the autocompletion list forward and align it with the insertion point instead of keeping it align with the text field.
In the sample screenshot above whenever I selected the autocomplete suggestion the text field only replaces K with the suggested item in the list, which results in Abadi Abadi Kurniawan.
These are what I'd like to achieve:
Whenever a suggestion is selected, the entire text field is replaced with the suggestion.
Keep the suggestion list aligned with the text field's left side.
Note: This is not a question about adding progress indicator behind a text field.
The Safari address bar uses a separate window. Apple has example project CustomMenus and it only takes an hour or two to customize it.
Developer session explaining what has to be done Key Event Handling in Cocoa Applications
If you want to be able to select multiple words you need to provide own FieldEditor (credits should go for someone else)
- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(nullable id)client;
{
if ([client isKindOfClass:[NSSearchField class]])
{
if (!_mlFieldEditor)
{
_mlFieldEditor = [[MLFieldEditor alloc] init];
[_mlFieldEditor setFieldEditor:YES];
}
return _mlFieldEditor;
}
return nil;
}
- (void)insertCompletion:(NSString *)word forPartialWordRange:(NSRange)charRange movement:(NSInteger)movement isFinal:(BOOL)flag
{
// suppress completion if user types a space
if (movement == NSRightTextMovement) return;
// show full replacements
if (charRange.location != 0) {
charRange.length += charRange.location;
charRange.location = 0;
}
[super insertCompletion:word forPartialWordRange:charRange movement:movement isFinal:flag];
if (movement == NSReturnTextMovement)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"MLSearchFieldAutocompleted" object:self userInfo:nil];
}
}
This only addresses half of your answer, but I believe you need to subclass NSTextView and implement the - (NSRange)rangeForUserCompletion method, returning the range of the entire string in the text field. This should make sure that it doesn't just autocomplete the most recently entered word.
If you want a custom menu, you're going to have to do that yourself, probably by implementing the -controlTextDidChange: method and displaying a custom view with a table when appropriate.
I have a segmented control that works lovely if you tap one of the segments BUT if you don't tap anything and let it sit at the natural resting spot which is the first segment it doesnt work
I tested this by tapping another segment and continuing the app and it worked, and i also tested by tapping another segment and then going back to the first segment and it worked
#IBAction func segmentedControl(sender: UISegmentedControl) {
switch segmenControl.selectedSegmentIndex {
case 0:
numberOfParticipants = "4"
case 1:
numberOfParticipants = "6"
case 2:
numberOfParticipants = "8"
case 3:
numberOfParticipants = "10"
case 4:
numberOfParticipants = "12"
case 5:
numberOfParticipants = "14"
case 6:
numberOfParticipants = "16"
default:
break
}
}
It makes sense since it is wrapped in an IBAction and nothing is being pressed therefore it's not being triggered. How do i fix this issue?
Edit
By doesn't work i mean if the segment that is highlighted says 4 AND the user taps a continue button (different button) then a variable gets updated with a string of "4" and then firebase gets updated to say x = 4
So what is happening is when you land on the page by default the 4 segment is highlighted and if you want 4 to be your option you would leave it alone and hit the continue button...my problem is that if you don't interact with the segment control and actually tap 4 then the code never gets run, but if you tapped 6 then back to 4 it would trigger
Your questions in not very clear in defining what exactly seems to be broken. What doesn't work if you don't tap it? In general there are 2 steps involved in using UISegmentedControls. In step 1 you set it in your initialization - i.e. viewDidLoad - via:
segmenControl.selectedSegmentIndex = your_initial_value
Of course your initial value cannot be numberOfParticipants because the control only has 6 values..
Then step 2 is something like your IBAction which looks fine. Your use of magic numbers is of course a bit problematic.
This is how I understand the question:
You have a "Continue" button and if you hit it, you want it to reflect the state of the segmented control. Correct?
If that's the case, you don't need the IBAction, just read segmentControl.selectedSegmentIndex directly in IBAction of the Continue button.
I understand your question and had the same problem myself.
I experimented as I did not want any Segment in my Segmented Control to be highlighted or selected at all as this would cause confusion to my users and if the highlighted start index was actually what the User required,then when pressed did not perform the Action within the Switch Case area.
So... I made the Index Value -1 and this does not highlight any part of the Segment at all, it works a treat for my requirements and makes the user select the desired segment.
I set this up within my ViewDidLoad()
mySegmentedControlOutlet.selectedSegmentIndex = -1
Ok so I have a segmentedControl which I need to dynamically remove and add segments to. This piece of code will remove the first segment but then doesnt set the correct segment to be selected. The strange thing is when I print it out all the numbers are correct it is just the highlighted segement on the screen which is always out by -1.
if ([outControl numberOfSegments]==4) {
int previous = [outControl selectedSegmentIndex];
if (previous>0) {
previous--;
}
[outControl removeSegmentAtIndex:0 animated:YES];
NSLog(#"setting to %d with %d segments", previous ,[outControl numberOfSegments]);
[outControl setSelectedSegmentIndex:previous];
}
Here is the log setting to 1 with 3 segments. With this log segment 0 is actually selected in the control and I cannot press segment 1 as the control thinks it is selected?
I can press segment 0 though even though that is the one being displayed as selected.
Here is a screen grab to try and clarify my issue.
image
The text in the cell is correct as cell 1 is actually selected as you can see by the log. But the highlighted cell is 0!? Its driving me crazy. It all works when adding segments its only when removing I get the issue.
Can anyone see where its going wrong??
Many thanks
Jules
I have noticed that even if i do not set the new selected segment I get the same results ie the wrong segment is selected.....?? Also this is all coded with cellForRowAtIndexPath if that helps anyone?
The code looks right yet behaves (wrongly) just as you described. It seems that the control gets in an awkward state when changing the selection in the same turn of the run loop as the segment deletion. But this works:
-(void)setSegmentedSelection:(NSNumber *)indexNum {
NSInteger index = [indexNum intValue];
[outControl setSelectedSegmentIndex:index];
}
// then instead of setting the selected index after the segment is removed,
// let the run loop return...
[self performSelector:#selector(setSegmentedSelection:) withObject:[NSNumber numberWithInt:previous] afterDelay:0.0];
I'm surprised that it doesn't work as you coded, but at least here's a workaround until we figure it out.
I'm trying to make a Completion when pressing tab, you get the first completion of all possibilities.
But, in a QWidget-based main window, pressing tab will make that QLineEdit lost focus, and completion popup hides after that.
Is there a way to fix it ?
Have you tried to subclass QLineEdit and intercept the key press event?
Alternatively you could set up an event filter.
Whew. It took me some time to figure this out :) Multiple times I have tried to solve this problem, but always gave up. Now, I dug enough to find the answer.
OP, please pardon me, because the code here is Python, but should be understandable and work for C++ as well.
Basically, the problem I had was "how to select an entry in the QCompleter"; I didn't notice before, but the answer is in the popup() method. QCompleter works with a model and a view, which contains the things to show.
You can change the current row as you wish, then get the index of that row in the model, then select it in the pop-up.
In my code, I subclassed QLineEdit, created a tabPressed signal which is emitted every time Tab is pressed. Then, connected this signal to a method of the same class which does this:
get the current index;
select the index in the popup;
advance to the next row.
As implementation, this is very trivial, but for my current purpose this is enough. Here's the skeleton (just for the tab part, it's missing the model and everything else).
class MyLineEdit(QLineEdit):
tabPressed = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._compl = QCompleter()
self.tabPressed.connect(self.next_completion)
def next_completion(self):
index = self._compl.currentIndex()
self._compl.popup().setCurrentIndex(index)
start = self._compl.currentRow()
if not self._compl.setCurrentRow(start + 1):
self._compl.setCurrentRow(0)
def event(self, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.tabPressed.emit()
return True
return super().event(event)
You may need to adjust/fix few things, but this is the basic idea.
EDIT:
For details see
http://www.qtcentre.org/threads/23518-How-to-change-completion-rule-of-QCompleter
There's a little issue: when Return is pressed, the things don't work properly. Maybe you can find a solution to this problem in the link above, or in the referenced resources therein. I'll fix this in the next few days and update this answer.
There is probably a better solution but one that comes to mind is to change the focus policy for all other widgets on the form to something that doesn't include "tab" focus. The only options that don't use the tab key are Qt::ClickFocus and Qt::NoFocus.
Can i maintain the selected state of UISegmentViewControl segments??
i.e can keep a segment appear selected even if the user selects another segment??
I dont seem to find anything that does this anywhere!!
This isn't possible out of the box. (See How can I enable multiple segments of a UISegmentedControl to be selected?.)
You could try something like this code to provide similar functionality.
I found a way arround this.I placed dark colored image behind each segment and set their hidden property to true.Then i decresed the alpha value of the uisegmented control.Then in the code when a segment is clicked i turn the visibility on or off accordingly,so multiple segments appear selected
Another solution might be using a category:
#import <UIKit/UISegmentedControl.h>
#interface UISegmentedControl (MultiSelect)
#end
Doing this, you have in principle access to private member variables of UISegmentedControl . In particular, you have access to the array holding the button segments, which you can manipulate according to your needs by overriding setSelectedSegmentIndex:selectedSegmentIndex: .However, for various reasons, the attributes declared as private still shouldn't be accessed directly, see this link. As also suggested there, you can rather abuse KVC. So the implementation could look as follows:
#implementation UISegmentedControl (MultiSelect)
- (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {
NSMutableArray *pArraySegments = [self valueForKey:#"segments"];
if ((pArraySegments) && (selectedSegmentIndex >= 0) && (selectedSegmentIndex < [pArraySegments count])) {
UIButton *pSegment = (UIButton*)[pArraySegments objectAtIndex:selectedSegmentIndex];
pSegment.selected ? (pSegment.selected = NO) : (pSegment.selected = YES);
}
}
#end
This works for me. However, since I now read this discussion, I'm not quite sure if this is really a valid approach.