UITextField highlight all text - iphone

I have searched through stackoverflow for a similar problem and found recommended solutions that worked for others but none of them worked for me so I'm beginning to suspect that it's something I haven't done properly.
It's very simple. All I want to have is that when the user taps on the uitextfield, the entire text within uitextfield get selected. The user can then proceed to delete it all, tap once and append from that point onwards or start typing to overwrite everything.
I have an action from the uitextfield and here's the snippet.
- (IBAction)didBeginEditDescription:(id)sender
{
NSLog(#"Description began edit.");
[self.txtfield selectall:self];
}
I know the method is called (evident by the NSLog). However, nothing happens and the cursor remains to be at the last position of the text. I have UITextFieldDelegate already so not sure what else I should look at?
FYI, this is being done to Xcode 5.0 and trying to develop for iOS 7.
Is there anything obvious that I'm missing?

I think you want to highlight all the text of selected UITextField. In that case, first you should identify which UITextField called that method (-didBeginEditDescription) and then you can call -selectAll for that particular UITextField.
Sample Code :
- (IBAction)didBeginEditDescription:(id)sender
{
NSLog(#"Description began edit.");
UITextField *txtFld = ((UITextField *)sender);
[txtFld selectAll:self];
}
Update :
-selectAll should work. I already implemented and it is working very well for me. Note that, you have written -selectall instead of -selectAll. You can also try like this :
[txtFld setSelectedTextRange:[txtFld textRangeFromPosition:txtFld.beginningOfDocument toPosition:txtFld.endOfDocument]];

Xamarin iOS:
nativeTextField.EditingDidBegin += (object sender, EventArgs eIos) =>
{
nativeTextField.PerformSelector(new Selector("selectAll"), null, 0.0f);
};
Xamarin.Forms custom renderer for iOS:
using System;
using CoreText;
using ObjCRuntime;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(Entry), typeof(MyEntryRenderer))]
namespace Hello.iOS
{
public class MyEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var nativeTextField = (UITextField)Control;
nativeTextField.EditingDidBegin += (object sender, EventArgs eIos) =>
{
nativeTextField.PerformSelector(new Selector("selectAll"), null, 0.0f);
};
}
}
}
Xamarin.Forms custom renderer for Android:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
EditText editText = null;
for (int i = 0; i < ChildCount; ++i)
{
Android.Views.View view = (Android.Views.View)GetChildAt(i);
if (view is EditText) editText = (EditText)view;
}
editText?.SetSelectAllOnFocus(true);
}
}

I found it was necessary to put call selectAll:self upon TouchDown: rather than editDidBegin:
Attach Touch Down to - (IBAction)didBeginEditDescription:(id)sender in InterfaceBuilder.

For Xamarin.Forms, create a custom renderer with this method:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement == null) return;
Control.EditingDidBegin += (sender, e) => Control.PerformSelector(new ObjCRuntime.Selector("selectAll"), null, 0.0f);
}

Related

Referencing to gameobject's renderer material after being instantiated from downloaded asset bundle not working

Hi! If you want to save time and still help please read this section and the last one to get glimpse of my problem (part 1 and 6). So much code was needed to fully present problem
Using Unity 2019.3.0b2
1.
Im creating WebGL application that allows you to customize your character via assets from downloaded asset bundles. So far I got downloading and instantiating work, but I also want to change downloaded gameobject material to custom color from color-picker. In this case I need to refer to adequate Renderer. I've got function that sends request and it goes like so:
private IEnumerator SendRequestCoroutine(UnityWebRequest request, UnityAction<UnityWebRequest> OnDownloadCompleteHandler, UnityAction<float> OnDownloadProgressHandler = null)
{
request.SendWebRequest();
while(!request.isDone)
{
if(OnDownloadProgressHandler != null)
OnDownloadProgressHandler.Invoke(request.downloadProgress);
yield return null;
}
// Has to fire once more because progress stops at around 0.87,
// never returning 1 unless download is finished.
if (OnDownloadProgressHandler != null)
OnDownloadProgressHandler.Invoke(1);
OnDownloadCompleteHandler.Invoke(request);
}
2.
I fire this coroutine like that:
public void DownloadAssetBundle(string url, ProgressBar bar = null)
{
if (isRequestSend)
{
Alerter.ShowMessage("Request has been already send, please wait untill complete.");
return;
}
UnityWebRequest request = HttpService.Instance.GetAssetBundleRequest(url);
if(bar != null)
{
HttpService.Instance.SendDownloadRequest
(
request,
(rq) => { OnDownloadAssetBundleCompleteHandler(rq); },
(rq) => OnDownloadProgressHandler(rq, bar)
);
isRequestSend = true;
}
else
{
HttpService.Instance.SendDownloadRequest
(
request,
(rq) => { OnDownloadAssetBundleCompleteHandler(rq); }
);
isRequestSend = true;
}
}
3.
OnDownloadAssetBundleCompleteHandler looks like this:
//Function that will handle asset bundle when completed.
private void OnDownloadAssetBundleCompleteHandler(UnityWebRequest request)
{
isRequestSend = false;
if(request.isHttpError || request.isNetworkError)
{
//Handle downloading error
Alerter.ShowMessage("Seems like there was a problem with downloading, try again.");
}
else
{
AssetBundle bundle;
//Handle content update
bundle = DownloadHandlerAssetBundle.GetContent(request);
AssetBundleInfo assetBundleInfo = bundle.LoadAllAssets<AssetBundleInfo>().FirstOrDefault();
if (assetBundleInfo == null)
{
//Handle error
Alerter.ShowMessage("Couldn't read information about this Character Part. AssetBundleInfo null exception.");
bundle.Unload(false);
return;
}
GameObject goToLoad = null;
goToLoad = bundle.LoadAsset<GameObject>(assetBundleInfo.ObjectName);
if (goToLoad == null)
{
Alerter.ShowMessage("Couldn't read information about this Character Part. Downloaded asset's gameobject null exception.");
bundle.Unload(false);
return;
}
Sticher.ConnectComponent(goToLoad, assetBundleInfo.PartType);
ColorSetter.Instance.ChangeSelectedBodyPart(assetBundleInfo.PartType);
bundle.Unload(false);
}
}
4.
Now the final step is to set adequate transform so my script will search for component of type Renderer, get its material of index 0 as current material to modify, class that contain ChangeSelectedBodyPart function looks like so:
using Assets.Scripts.Models.Enums;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColorSetter : MonoBehaviour
{
public Renderer rend;
public ColorPicker picker;
public static ColorSetter Instance;
private void Awake()
{
if(Instance != null)
{
Destroy(this);
}
else
{
Instance = this;
DontDestroyOnLoad(this);
}
}
// Start is called before the first frame update
void Start()
{
picker.onValueChanged.AddListener(color =>
{
if (rend == null)
return;
rend.material.SetColor("_BaseColor", color);
}
);
}
public void ChangeSelectedBodyPart(AvatarPartType p)
{
switch(p)
{
case AvatarPartType.ClothesUpper:
SetActiveMaterial(Sticher.Instance.Clothes_Upper);
break;
case AvatarPartType.ClothesLower:
SetActiveMaterial(Sticher.Instance.Clothes_Lower);
break;
case AvatarPartType.Shoes:
SetActiveMaterial(Sticher.Instance.Shoes);
break;
case AvatarPartType.Hair:
SetActiveMaterial(Sticher.Instance.Hair);
break;
case AvatarPartType.Skin:
SetActiveMaterial(Sticher.Instance.Skin);
break;
}
}
private void SetActiveMaterial(Transform parent)
{
rend = parent.GetComponentInChildren<Renderer>();
}
}
5.
PS. parent has only one child that contains Renderer component
Now, finally, problem is that I don't get proper material reference, I got the old one that is being set via toggle button, simply as that:
public void OnValueChanged(bool value)
{
if(value)
{
ColorSetter.Instance.ChangeSelectedBodyPart(PartType);
ButtonManager.Instance.RemoveAllButtonsFromPartsWindow();
ButtonManager.Instance.PopulatePartsPanelWithAvatarPartsOfType(PartType);
}
}
6.
So in conclusion when I press on "toggle button" that represents some avatar body/clothing part it sets its parent and material properly via function, even after asset bundle has been downloaded (but I have to click the same toggle again to make it work), but when I fire the same function in OnDownloadAssetBundleCompleteHandler just after asset been downloaded it doesn't work :S Why? Is it related with asset unloading speed? Any tips on fixing this?
In Game View it behave like that:
I fixed it. Since you can't use DestoyImmediate like #derHugo said because it can cause reference errors or even it could destroy assets permamently I had to use Destroy() instead before Instantiating new gameobject from assetbundle, however Destroy() will delete given object at the end of the frame while I try to access Renderer component on freshly instantiated GameObject just at the same frame, before old one is acutally destoryed. I fixed it yielding one frame using yield return new WaitForEndOfFrame(); just after function that takes care of destroying old GameObjects before trying to access new GameObject.

checking paragraph property loses the selection

in my vsto addin i have some simple code on a timer
private void MainTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!dialogopen & Application.Documents.Count > 0)
{
var doc = Application.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>().ToList();
foreach (var obj in pars2)
{
if (obj.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText )//PROBLEM HERE
{
};
}
}
}
as soon as it reaches the line that checks the outlinelevel, even if i dont do a thing, the selection in the activedocument gets lost
of course the user cant use a plugin which keeps on canceling his selection...
googling didnt give me a thing
thanks
EDIT1
I tried making a static function for checking the styles, but it did not help. Here's the code
static public class Helpers
{
static public Word.Paragraph checkPars(List<Word.Paragraph> pars)
{
return pars.FirstOrDefault();//(x) => x.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText);
}
}
As you can see, I had to remove the actual check, since it was causing the cursor to blink and lose selection
please advise
We use the Application.ScreenUpdating = true; and this keep the selection for all properties in Paragraph except for the Range property.
Then, we tried to access the range via Reflection and this was the solution.
Range rng = (Range)typeof(Paragraph).GetProperty("Range").GetValue(comObj);
We tried to eliminate querying ActiveDocument thinking that that might have had side-effects that were causing the problem but that was not the case.
Then, we confirmed that the selection was not "lost" and screen-updating is the only problem, so we tried restoring the UI with Application.ScreenRefresh and while it did work, it causes the screen to flicker every time the timer fires and this is not good enough.
Finally, knowing that it's only a UI problem, I tried simply switching off Application.ScreenUpdating...
in ThisAddin
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Timer timer = new Timer(2000);
timer.Elapsed += (s, t) =>
{
var scrnUpdating = Application.ScreenUpdating;
Application.ScreenUpdating = false;
MainTimer.onElapsed(Application, t);
if (scrnUpdating)
Application.ScreenUpdating = true;
};
timer.Start();
}
In another class library (note that it's static, I still think this is the best way)...
public static class MainTimer
{
public static void onElapsed (Word.Application state, System.Timers.ElapsedEventArgs e)
{
if (state.Documents.Count > 0)
{
var doc = state.ActiveDocument;
Word.InlineShapes shps;
Word.Paragraphs pars;
try
{
pars = doc.Paragraphs;
}
catch (Exception)
{
return;
}
var pars2 = pars.Cast<Word.Paragraph>()
.Where(p => p.OutlineLevel == Word.WdOutlineLevel.wdOutlineLevelBodyText)
.Select(p => p) // do stuff with the selected parragraphs...
.ToList();
}
}
}
And this works for me.
The selection remains and is displayed in the UI without flicker.
I also eliminated some premature enumeration from your code: you don't meed the .ToList() before the foreach.

How to find framework element inside viewmodel using Prism

I previously used Caliburn.Micro for my projects before universal windows application. Now I'm porting my apps to universal windows and decided to use Prism Library. Because there are lots of uwp sample for that. But I'm too beginner and don't know how to convert my old viewmodels.
I'm using webview to show some generated html. In caliburn I can find webview in viewmodel using OnViewLoaded event;
protected override void OnViewLoaded(object view)
{
base.OnViewLoaded(view);
var frameworkElement = view as FrameworkElement;
if (frameworkElement == null)
throw new ArgumentException();
var browser = frameworkElement.FindName("browser") as WebView;
if (browser == null)
throw new ArgumentException();
_webBrowser = browser;
}
But I didn't find any event can provide this. In prism there are only OnNavigatedTo and OnNavigatingFrom events.
Do prism have workaround for that?
Sorry about late reply,
I aggree with Igor and Tseng that will break MVVM pattern. But I'm trying to do something complex. Maybe there is a way of doing with it MVVM but I don't want to lose too much time on this.
What I found solution for the problem is as following. I wrote a VisualHelper
public class VisualHelper
{
public static T FindVisualChildInsideFrame<T>(DependencyObject depObj) where T : DependencyObject
{
var frame = FindVisualChild<Frame>(depObj);
if (frame != null && frame.Content is Page)
return FindVisualChild<T>(frame.Content as Page);
return null;
}
public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
return (T)child;
}
T childItem = FindVisualChild<T>(child);
if (childItem != null)
return childItem;
}
}
return null;
}
}
In my viewmodel, using following code finds WebView control. I'm using SplitView control thats why I'm using FindVisualChildInsideFrame method.
public override void OnNavigatedTo(NavigatedToEventArgs e, Dictionary<string, object> viewModelState)
{
base.OnNavigatedTo(e, viewModelState);
var browser = VisualHelper.FindVisualChildInsideFrame<WebView>(Window.Current.Content);
}

CellTree "Show More" programmatically

does anyone know how to trigger the "Show More" functionality of a GWT CellTree programmatically, without having to click on the Show More button?
My aim is to implement a kind of pager that increments the number of elements displayed when the user scrolls down a ScollPanel, so it would be something like:
//inside pager class
onScroll(ScrollEvent)
{
//here I would call CellTree's show more
}
I've been looking the CellTree and CellTreeNodeView classes code but I couldn't find a clear way to do it.
I know the class CellTreeNodeView has a showMore function which is the one who performs this action, but I don't know how to get it called from another class. I'd need a CellTreeNodeView object, and dont' know how to get it.
Thanks!
It is a package protected method in a package protected class CellTreeNodeView i.e only code in com.google.gwt.user.cellview.client can invoke it.
void showMore()
Extremely hacky solution
1) The only way around it is . Copy CellTreeNodeView and CellTree into your code base (maintain the package )
2) Change the accessors to public to allow you to invoke showMore as per your requirement.
3) Ensure you test for all possible flows.
4) Ensure the copied classes in your code base appear in a higher classpath hieararchy to GWT Compiler than gwt-user jar thus ensuring your modified classes get picked up rather than original ones.
Finally I got it working exactly as I wanted, and without having to copy the code from the protected original GWT.
The point was firing the same event as the "Show more" button, so I created a fake onMouseDown event, and triggered it with the show more button as the target:
final ScrollPanel sp = new ScrollPanel();
sp.addScrollHandler(new ScrollHandler() {
#Override
public void onScroll(ScrollEvent event)
{
int maxScrollBottom = sp.getWidget().getOffsetHeight()
- sp.getOffsetHeight();
if (sp.getVerticalScrollPosition() >= maxScrollBottom) {
NativeEvent clickEvent = Document.get().createMouseDownEvent(0,0,0,0,0,false,false,false,false,0);
Element target = (Element) cellTree.getCellTree().getElement().getLastChild().getFirstChild().getLastChild();
target.dispatchEvent(clickEvent);
}
}
});
Thank you a lot, anyway! :D
My workaround is this one:
public static void makeShowMoreVisible(Element element, boolean isVisible) {
ArrayList<Element> result = new ArrayList<Element>();
findShowMore(result, element);
for (Element elt : result) {
if (isVisible) {
element.getStyle().clearDisplay();
} else {
element.getStyle().setDisplay(Display.NONE);
}
}
}
private static void findShowMore(ArrayList res, Element element) {
String c;
if (element == null) {
return;
}
if (element.getInnerText().equals("Show more")) {
res.add(element);
}
for (int i = 0; i < DOM.getChildCount(element); i++) {
Element child = DOM.getChild(element, i);
findShowMore(res, child);
}
}

eclipse rcp :how to select a single cell in tableviewer?

hwo can I change the default selection behaviour of tables, I want to make a cell selected when user click it and make it editable when user double click it.
with #nonty 's help, I get what I want.
here is my cell highlighter implemention:
package com.amarsoft.rcputil;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
public class DefaultCellFocusHighlighter extends FocusCellOwnerDrawHighlighter {
public DefaultCellFocusHighlighter(ColumnViewer viewer) {
super(viewer);
}
protected boolean onlyTextHighlighting(ViewerCell cell) {
return false;
}
protected Color getSelectedCellBackgroundColor(ViewerCell cell) {
return cell.getControl().getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);
}
protected Color getSelectedCellForegroundColor(ViewerCell cell) {
return cell.getControl().getDisplay().getSystemColor(SWT.COLOR_WHITE);
}
protected Color getSelectedCellForegroundColorNoFocus(ViewerCell cell) {
return cell.getControl().getDisplay().getSystemColor(SWT.COLOR_WHITE);
}
protected Color getSelectedCellBackgroundColorNoFocus(ViewerCell cell) {
return cell.getControl().getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);
}
protected void focusCellChanged(ViewerCell newCell, ViewerCell oldCell) {
super.focusCellChanged(newCell, oldCell);
}
}
the code to use it :
TableViewerFocusCellManager focusCellManager = new TableViewerFocusCellManager(tv,new DefaultCellFocusHighlighter(tv));
ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(tv) {
protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) {
return event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL
|| event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION
|| (event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED && event.keyCode == SWT.CR)
|| event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC;
}
};
TableViewerEditor.create(tv, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL
| ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR
| ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION);
but I got new problem :
when I double click on cell to edit it's value, there is a little area at the left side of the cell is still highlighted with dark blue color
I know why :
When a text control is created with a border, the operating system includes a platform specific inset around the contents of the control.
still seeking for fixing...
Have a look at these two JFace Snippets:
Snippet036FocusBorderCellHighlighter - Demonstrates keyboard navigation by highlighting the currently selected cell with a focus border showing once more the flexibility of the new cell navigation support
Snippet034CellEditorPerRowNewAPI - Demonstrates different CellEditor-Types in one COLUMN with 3.3-API of JFace-Viewers
After digging through the code, I found the following method in the ColumnViewer class:
/**
* Hook up the editing support. Subclasses may override.
*
* #param control
* the control you want to hook on
*/
protected void hookEditingSupport(Control control) {
// Needed for backwards comp with AbstractTreeViewer and TableTreeViewer
// who are not hooked this way others may already overwrite and provide
// their
// own impl
if (viewerEditor != null) {
control.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
// Workaround for bug 185817
if (e.count != 2) {
handleMouseDown(e);
}
}
public void mouseDoubleClick(MouseEvent e) {
handleMouseDown(e);
}
});
}
}
So, I overrode that function within my TableViewer subclass:
#Override protected void hookEditingSupport(Control control) {
// We know there should be an editor avaiable
// if (viewerEditor != null) {
control.addMouseListener(new MouseAdapter() {
public void mouseDown(MouseEvent e) {
// Workaround for bug 185817
if (e.count != 2) {
// We don't want to edit on single clicks
// handleMouseDown(e);
}
}
public void mouseDoubleClick(MouseEvent e) {
// This method is private, so copy the implementation
// handleMouseDown(e);
ViewerCell cell = getCell(new Point(e.x, e.y));
e.count--; // A hack to make things work - pretend like it's a single click
if (cell != null) {
triggerEditorActivationEvent(new ColumnViewerEditorActivationEvent(
cell, e));
}
}
});
// }
}
This works for me. Tell me if it works for you.