NumberPicker does not work with keyboard input value in Xamarin Android - c#

I have a numberpicker control in android activity. It works good when clicking those "+" and "-" buttons. But when I enter a number from keyboard it and try to get the current entered value in program, it does not give value which was entered by keyboard. I am working with C# Xamarin android.
is there any key press event or something which can help?

You could create set a Custom OnEditorActionListener on the EditText of the NumberPicker:
NumberPicker picker;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.test);
picker = FindViewById<NumberPicker>(Resource.Id.numberPicker);
picker.MaxValue = 40;
picker.MinValue = 1;
EditText editText= (EditText)picker.GetChildAt(1);
editText.SetOnEditorActionListener(new CustomActionListener());
}
public class CustomActionListener : Java.Lang.Object,EditText.IOnEditorActionListener
{
public bool OnEditorAction(TextView v, Android.Views.InputMethods.ImeAction actionId, KeyEvent e)
{
if(actionId == Android.Views.InputMethods.ImeAction.Done)
{
// Here is you number
string countNumber = v.Text;
}
return true;
}
public IntPtr Handle
{
get { return base.Handle; }
}
public void Dispose()
{
base.Dispose();
}
}

Related

How to prevent Xamarin forms, a custom menu and WebView renderer with EvaluateJavascript from freezing?

I have created a custom menu item which appears in the default menu which pops up when selecting text on my custom WebView.
On clicking on the menu item it calls EvaluateJavascript to get the selected WebView text, and then passes the text to another page.
However after performing this action once or twice, some text on certain areas of the screen start to become unresponsive to clicks eg. text on the parts of the WebView become unselectable, clicks on that part of the screen on other pages becomes unresponsive and even the soft keyboard becomes unclickable in some spots. If this continues for a while sometimes my app will then suddenly freeze the entire operating system and I have to soft reset my phone. It appears that there maybe some serious memory leakage going on.
I create my custom menu item in the MainActivity class:
public override void OnActionModeStarted(ActionMode mode)
{
if (Root.IsCurrentPageType<DictPage>() && DictP.IsWebViewFocused())
{
IMenu menu = mode.Menu;
menu.Add("To Notes");
menu.GetItem(0).SetOnMenuItemClickListener(new MyMenuItemOnMenuItemClickListener(this, mode));
}
base.OnActionModeStarted(mode);
}
It is then handled in the Listener class...
public class MyMenuItemOnMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener
{
private MainActivity mContext;
ActionMode _mode;
public MyMenuItemOnMenuItemClickListener(MainActivity activity, ActionMode mode)
{
this.mContext = activity;
_mode = mode;
}
public bool OnMenuItemClick(IMenuItem item)
{
WEB.CopyToMainNotes();
Device.BeginInvokeOnMainThread(() =>
{
//close menu if clicked
_mode?.Finish();
});
return true;
}
}
...which calls CopyToMainNotes on my derived WebView class and its associated Renderer and EventHandler classes:
public class WebViewEx : Xamarin.Forms.WebView
{
public static WebViewEx WEB;
//Namespace
//YourClass
public event WebViewExEventHandler CallNativeMethodEvent;
public void CallNativeMethod(WebViewExEventType type)
{
WebViewExEventArgs e = new WebViewExEventArgs();
e.EventType = type;
CallNativeMethodEvent?.Invoke(this, e);
}
public WebViewEx()
{
WEB = this;
}
public void CopyToMainNotes()
{
Device.BeginInvokeOnMainThread(() =>
{
CallNativeMethod(WebViewExEventType.copyToMainNotes);
});
}
}
public delegate void WebViewExEventHandler(object sender, WebViewExEventArgs e);
public class WebViewExEventArgs : EventArgs
{
public enum WebViewExEventType { copyToMainNotes };
public WebViewExEventType EventType = WebViewExEventType.copyToMainNotes;
public WebViewExEventArgs() : base()
{
}
}
public class WebViewExRenderer : WebViewRenderer
{
public WebViewExRenderer(Android.Content.Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (Control != null)
{
WebViewEx ex = e.NewElement as WebViewEx;
ex.CallNativeMethodEvent += WebViewEx_CallNativeMethodEvent;
}
}
internal class JavascriptCallback : Java.Lang.Object, IValueCallback
{
public JavascriptCallback(Action<string> callback)
{
_callback = callback;
}
private Action<string> _callback;
public void OnReceiveValue(Java.Lang.Object value)
{
_callback?.Invoke(Convert.ToString(value));
}
}
private void WebViewEx_CallNativeMethodEvent(object sender, WebViewExEventArgs e)
{
switch (e.EventType)
{
case WebViewExEventType.copyToMainNotes:
{
CopyToMainNotes();
break;
}
}
}
public void CopyToMainNotes()
{
string script = "(function(){ return window.getSelection().toString()})()";
var response = string.Empty;
Control?.EvaluateJavascript(script, new JavascriptCallback((r) =>
{
response = r;
Device.BeginInvokeOnMainThread(() =>
{
DPage.CopyThisTextToAnotherPage(response.ToString().Trim('\"'));
});
}));
}
}
The CopyToMainNotes method above is where the EvaluateJavascript takes place and the selected text finally gets sent to another page.
Any ideas where I might be going wrong here? Thanks in advance!

Getting mouse click in design time, but also let the control be selected at the same time

I am creating a custom control that acts like the TabControl. I want the tab headers to be clickable in design time, just like the TabControl. Using the sample code I found on the Microsoft site, I wrote the following code. It works, but there is one problem.
As for the real TabControl, if you click a tab header when the TabControl has not been selected, the selected tab changes, AND the TabControl gets selected showing the resizing border which has a moving handle and a small button for "TabControl Tasks".
Doing the same thing with my code below only changes the selected tab header; it does not make my control be selected. I think I need to tell the Visual Studio Designer to select my control, somehow. But how?
public class MyDesigner : System.Windows.Forms.Design.ControlDesigner
{
private Adorner MyAdorner;
public override void Initialize(IComponent component)
{
base.Initialize(component);
MyAdorner = new Adorner();
this.BehaviorService.Adorners.Add(MyAdorner);
MyAdorner.Glyphs.Add(new MyGlyph(BehaviorService, (MyTabControl)Control));
}
protected override void Dispose(bool disposing)
{
if (disposing && MyAdorner != null)
{
BehaviorService b = BehaviorService;
if (b != null)
{
b.Adorners.Remove(MyAdorner);
}
}
}
class MyGlyph : Glyph
{
MyTabControl TargetControl;
BehaviorService behaviorSvc;
public MyGlyph(BehaviorService behaviorSvc, MyTabControl targetControl)
:base(new ClickingBehaviour())
{
this.behaviorSvc = behaviorSvc;
this.TargetControl = targetControl;
}
private void OnMouseClick(MouseButtons button, Point adornerPoint)
{
var screenPoint = behaviorSvc.AdornerWindowPointToScreen(adornerPoint);
var targetPoint = TargetControl.PointToClient(screenPoint);
TargetControl.DesignTimeClick(button, targetPoint);
}
public override Rectangle Bounds
{
get
{
Point edge = behaviorSvc.ControlToAdornerWindow(TargetControl);
Size size = TargetControl.Size;
Rectangle bounds = new Rectangle(edge, size);
return bounds;
}
}
public override Cursor GetHitTest(Point p)
{
Cursor handled = null;
if (Bounds.Contains(p))
{
var screenPoint = behaviorSvc.AdornerWindowPointToScreen(p);
var targetPoint = TargetControl.PointToClient(screenPoint);
if(TargetControl.IsHeaderArea(targetPoint))
handled = Cursors.Default;
}
return handled;
}
public override void Paint(PaintEventArgs pe)
{
}
class ClickingBehaviour : Behavior
{
public override bool OnMouseDown(Glyph g, MouseButtons button, Point mouseLoc)
{
MyGlyph myG = g as MyGlyph;
myG.OnMouseClick(button, mouseLoc);
return base.OnMouseDown(g, button, mouseLoc);
}
}
}
}
I could not figure out how to do it with the approach which uses an Adorner as above. So, I resorted to using Win32 message (I tried to avoid using Win32 for interoperability).
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0201 && m.WParam.ToInt32() == 0x0001)
{
var target = (Control as MyTabControl);
if (true) //how to know if focused?
{
var lparam32 = m.LParam.ToInt32();
int lowWord = lparam32 & 0xffff;
int highWord = lparam32 >> 16;
Point p = new Point(lowWord, highWord);
if (target.IsHeaderArea(p))
{
target.DesignTimeClick(MouseButtons.Left, p);
}
}
}
base.WndProc(ref m);
}
It works, but the only minor problem is that the tab index changes at the first click when the tab is not selected. Clicking a tab on a real TabControl when it is not selected does not change the tab but only selects the tab. But I guess I can live with this minor difference.

C# Combobox user control does not funtion as it should

I am fixing a c# project that uses a user control named CompleteComboBox.
It functions partly.
The backspace does not work.
The first time the user enters a string into the textbox part, the list opens as it should, and stands on the right line. The second time - the list does not open but it does show the matched line in the textbox part. Then, if i open the list and start writing the beginning of one of the items but then click one of the items and press enter - this item is not selected rather the item that was selected while entering letters in the text box part.
Hope I am understood.
Here is the code:
namespace BestInvest.UserControls
{
public partial class CompleteComboBox : System.Windows.Forms.ComboBox
{
public event System.ComponentModel.CancelEventHandler NotInList;
private bool _limitToList = true;
private bool _inEditMode = false;
bool start;
public CompleteComboBox()
: base()
{
start = true;
this.Text = ClsConsts.InitializeTextForCombo;
}
[Category("Behavior")]
public bool LimitToList
{
get { return _limitToList; }
set { _limitToList = value; }
}
protected virtual void OnNotInList(System.ComponentModel.CancelEventArgs e)
{
if (NotInList != null)
{
NotInList(this, e);
}
}
protected override void OnTextChanged(System.EventArgs e)
{
if (_inEditMode)
{
string input = Text;
int index = FindString(input);
if (index >= 0)
{
_inEditMode = false;
SelectedIndex = index;
_inEditMode = true;
Select(input.Length, Text.Length);
//base.DroppedDown = true;
}
}
base.OnTextChanged(e);
}
protected override void OnValidating(System.ComponentModel.CancelEventArgs e)
{
if (this.LimitToList)
{
int pos = this.FindStringExact(this.Text);
if (pos == -1)
{
OnNotInList(e);
}
else
{
this.SelectedIndex = pos;
}
}
base.OnValidating(e);
}
protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
if (start)
{
base.DroppedDown = true;
//else
start = false;
}
if (e.KeyCode == Keys.Enter)
{
base.DroppedDown = false;
start = true;
}
_inEditMode = true;
base.OnKeyDown(e);
}
}
}
Your code is messy. Look at the start flag. It is not set to true in all cases you would expect. That's why first time behavior is different from second time.
Your OnKeyDown event will not trigger on all keys you would expect. That's why backspace doesn't work. There are several posts about detecting backspace out there: See for example this one

Handle delete in EditText Xamarin.Android

I am facing a problem. I have 6 EditTexts. The content of each of them gives a total of 6 digits which is a password. If the password is correct, the user is being sent to another Activity. My problem is that if I try to delete, I am not able to handle a key press event, which will delete the content of each and every one of them, starting from the last.
I have implemented IOnKeyListener interface as follows:
public class MainActivity :Activity, View.IOnKeyListener
{
public bool OnKey(View v, Keycode keyCode, KeyEvent e)
{
if (e.Action == KeyEventActions.Down && keyCode.Equals(Keycode.Del))
{
return true;
}
return false;
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
EditText ed = FindViewById<EditText>(Resource.Id.editText_vonalkod);
ed.SetOnKeyListener(this);
}
}

how do I make a WinForms ListBox who's items toggle on and off

The functionality I'm after is a cross between a check list box and a list box in multi selection mode.
For list box items A and B
A then B results in a single selection that moves from A to B.
A then control-click B results in a multi-selection of A and B.
(What I want is):
A then A results in an A toggling on and off.
I thought this would be easy but I can't figure it out. Maybe I'm missing something obvious or maybe I'm thinking the wrong way and nobody really wants a listbox whos items toggle on/off.
If you set SelectionMode to MultiSimple this gets you the control-click multi-selection and the toggling on and off.
To get the moving selection to work you could handle the SelectedIndexChanged event and add some logic to de-select the other items if control isn't pressed. If I have more time later I could try to create some basic code for it, but this should be somewhere to start.
You already have the behavior you want if you set the ListBox.SelectionMode to MultiExtended and hold down control when making a selection.
If I understood correctly your problem, you want a ListBox with SelectionMode.One that can toggle selections with CTLR modifier similarly to SelectionMode.MultiSimple and SelectionMode.MultiExtented. Below my answer, just set ToggleSingleSelection to true. Also as a bonus it provides items click events that fires also when clicking already selected items.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Common
{
public class ListBoxEx : ListBox
{
public event ItemClickedEventHandler ItemClick;
public event ItemClickedEventHandler ItemDoubleClick;
/// <summary>
/// Toggle selections when list has SelectionMode.One
/// </summary>
public bool ToggleSingleSelection { get; set; }
int _PreSelectedIndex = -1;
int _PrevClickedItem = -1;
protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);
}
protected override void WndProc(ref Message m)
{
const int WM_LBUTTONDOWN = 0x201;
switch (m.Msg)
{
case WM_LBUTTONDOWN:
// NOTE: Unfortunately SelectedIndex is already setted before OnMouseDown,
// so we must intercept mouse click even before to compare
_PreSelectedIndex = SelectedIndex;
break;
}
base.WndProc(ref m);
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
// Reset clicked event, also for double click
_PrevClickedItem = -1;
int selectedIndex = SelectedIndex;
if (selectedIndex != -1)
{
Rectangle selectedItemRectangle = GetItemRectangle(selectedIndex);
if (selectedItemRectangle.Contains(e.Location))
{
_PrevClickedItem = selectedIndex;
// Check when to toggle selection
if (SelectionMode == SelectionMode.One && ToggleSingleSelection && ModifierKeys.HasFlag(Keys.Control)
&& _PreSelectedIndex != -1 && selectedIndex == _PreSelectedIndex)
{
SelectedIndex = -1;
}
if (_PrevClickedItem != -1)
OnItemClick(new ItemClickedEventArgs() { ItemIndex = _PrevClickedItem });
}
}
}
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
base.OnMouseDoubleClick(e);
if (_PrevClickedItem != -1)
OnItemDoubleClick(new ItemClickedEventArgs() { ItemIndex = _PrevClickedItem });
}
protected virtual void OnItemDoubleClick(ItemClickedEventArgs args)
{
ItemDoubleClick?.Invoke(this, args);
}
protected virtual void OnItemClick(ItemClickedEventArgs args)
{
ItemClick?.Invoke(this, args);
}
}
public class ItemClickedEventArgs : EventArgs
{
public int ItemIndex { get; set; }
}
public delegate void ItemClickedEventHandler(Control sender, ItemClickedEventArgs args);
}

Categories

Resources