Goal:
When ever 6 digit entered on ID_Display, It would hide the keyboard.
Problem:
Keyboard wouldnt hide unless Keyboard "Enter" is press
public void keyboard_hide_Listener() {
ID_Display = (EditText) findViewById(R.id.ID_display);
if (ID_Display != null) {ID_Display.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (event != null && (ID_Display.getText().length()>=6)) { //event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
System.out.println("Edit Text Length: " +ID_Display.getText().length());
in.hideSoftInputFromWindow(ID_Display.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
return true;
}
return false;
}
});
}
}
(ID_Display.getText().length()>=6
You should probably go with v.GetText() instead of ID_display
Related
Here's my problem:
In my app, I have set ChoiceMode(CHOICE_MODE_MULTIPLE_MODAL) and the method of MultiChoiceModeListener for my ListView in order to allow user to delete items in the list by using context menu. I have put the following code in onActionItemClicked method and everything work fine:
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
//Clear the list of selected item's id when the user exit the context menu bar.
mSelectedItemIdList.clear();
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.menu_select_delete:
deleteSelectedItem();
mode.finish();
return true;
default:
return false;
}
}
private void deleteSelectedItem(){
int totalRowDeleted = 0;
if (!mSelectedItemIdList.isEmpty()){
for (int i = 0; i < mSelectedItemIdList.size(); i++){
long idInDatabase = mSelectedItemIdList.get(i);
Uri selectedItemUri = ContentUris.withAppendedId(TimeEntry.CONTENT_URI, idInDatabase);
int rowDeleted = getContentResolver().delete(selectedItemUri, null, null);
if (rowDeleted != 0){
totalRowDeleted++;
}
}
}
if (totalRowDeleted == 0){
Toast.makeText(MainActivity.this, getString(R.string.delete_error_message), Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, totalRowDeleted + " " + getString(R.string.delete_success_message), Toast.LENGTH_SHORT).show();
}
But after I added the AlertDialog for confirmation like this:
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()){
case R.id.menu_select_delete:
showDeleteSelectedConfirmationDialog();
mode.finish();
return true;
default:
return false;
}
}
private void showDeleteSelectedConfirmationDialog(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.delete_selected_confirmation));
builder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
deleteSelectedItem();
}
});
builder.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (dialog != null){
dialog.dismiss();
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
The App doesn't crash but deleteSelectedItem() doesn't work anymore! Somehow the program doesn't reach the things in the for loop inside the method. Maybe there are some simple mistakes I have made. Can anyone help me?
I solved the problem.
The onDestroyActionMode() method is called everytime the AlertDialog show up. So, I have deleted the code in onDestroyActionMode() and add the code for clearing my list after the records are deleted.
private void deleteSelectedItem(){
int totalRowDeleted = 0;
if (!mSelectedItemIdList.isEmpty()){
for (int i = 0; i < mSelectedItemIdList.size(); i++){
long idInDatabase = mSelectedItemIdList.get(i);
Uri selectedItemUri = ContentUris.withAppendedId(TimeEntry.CONTENT_URI, idInDatabase);
int rowDeleted = getContentResolver().delete(selectedItemUri, null, null);
if (rowDeleted != 0){
totalRowDeleted++;
}
}
}
if (totalRowDeleted == 0){
Toast.makeText(MainActivity.this, getString(R.string.delete_error_message), Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(MainActivity.this, totalRowDeleted + " " + getString(R.string.delete_success_message), Toast.LENGTH_SHORT).show();
//Clear the list of selected item's id after delete the records.
mSelectedItemIdList.clear();
}
I implemented a navigation drawer and had used fragments. Now i can switch to fragments from the drawer menu. But when i press back, my app closes from that fragment and don't know how to go back to the main activity.
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
displaySelectedScreen(id);
return true;
}
private void displaySelectedScreen(int id) {
Fragment frag = null;
switch (id) {
case R.id.trigger:
break;
case R.id.setup:
if (android.os.Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.parseColor("#7B1FA2"));
}
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#8E24AA")));
frag = new SettingsF();
break;
case R.id.recordings:
if (android.os.Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.parseColor("#4E342E"));
}
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#8D6E63")));
break;
case R.id.howto:
if (android.os.Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.parseColor("#7B1FA2"));
}
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#8E24AA")));
break;
case R.id.about:
if (android.os.Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.parseColor("#7B1FA2"));
}
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#8E24AA")));
break;
case R.id.email_us:
if (android.os.Build.VERSION.SDK_INT >= 21) {
getWindow().setStatusBarColor(Color.parseColor("#7B1FA2"));
}
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#8E24AA")));
break;
}
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_main, frag);
ft.addToBackStack(ft.getClass().getSimpleName()).commit();
}
DrawerLayout drawer = findViewById(R.id.drawer);
drawer.closeDrawer(GravityCompat.START);
}
And here is the setting fragment only:
public class SettingsF extends ListFragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_settings, container, false);
String[] datasource = {"Trusted Contacts", "Custom Text Set-Up"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), R.layout.rowlayout, R.id.txtitems, datasource);
setListAdapter(adapter);
setRetainInstance(true);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("Context Set-Up");
}
public void onListItemClick(ListView l, View view, int position, long id) {
ViewGroup viewGroup = (ViewGroup) view;
TextView tv = (TextView) viewGroup.findViewById(R.id.txtitems);
Toast.makeText(getActivity(), tv.getText().toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onResume() {
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener( new View.OnKeyListener()
{
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
//Already Used Intent, doesn't work
return true;
}
return false;
}
} );
super.onResume();
}
}
I updated the question. I already used addToBackStack(), then overrided the method onResume() but still the app terminates when pressing the back button.
I'm really that new to this, so don't misunderstand me what did i implemented throughout the codes.
Thanks In Advance
for Hardware backbutton
add this code in onResume method in fragment
//You need to add the following line
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener()
{
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
//here use intent to call mainActivity
return true;
}
return false;
}
} );
hope this will help you
Add this line after ft.replace():
ft.addToBackStack(null);
This line will make it so that each time you select an item from the navigation drawer, a history of fragments is built up. Then when you press the back button, you'll go back through the history. If you have no history items, the app will close.
A more sophisticated implementation might use a name argument (like "FragA" or "FragB") instead of null as the argument for addToBackStack(), and then check to see if your fragment already exists in the back stack instead of always opening a new one. That way if you went A->B->A->B->A->B you wouldn't have three copies of A and two copies of B in the history.
I am working on an Xamarin.Forms project specifically for the iOS platform. I have an Editor control and a Button control next to each other. When I focus the editor, enter some text, and click the button it appears the command is not being fired but rather the keyboard is simply closing. I then have to tap the add button again for the command to be fired.
<StackLayout Orientation="Horizontal">
<Editor HorizontalOptions="FillAndExpand"
Text="{Binding EditorText}"/>
<Button Text="Add"
Command="{Binding AddCommand}"/>
</StackLayout>
I have tried creating a custom renderer that prevents the keyboard from closing initially and then close it after a delay. That allows the command to be fired, but I am stuck with the keyboard being open.
public class KeyboardEditorRenderer : EditorRenderer
{
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == VisualElement.IsFocusedProperty.PropertyName)
{
if (Control != null)
{
Control.ShouldEndEditing = (UITextView textField) =>
{
Task.Delay(10).ContinueWith(_ =>
{
// THIS DOES NOT WORK
textField.EndEditing(true);
});
return false;
};
}
}
base.OnElementPropertyChanged(sender, e);
}
}
My ideal solution is that you are able to enter text, tap the add button, and the keyboard closes and the command executes simultaneously. Any ideas on how to achieve this?
EDIT: It turns out the problem is with the custom renderer I use for the page. The custom renderer resizes the page when the keyboard appears so that it does not cover my editor field.
public class KeyboardPageRenderer : PageRenderer
{
private bool keyboardShowing;
private NSObject keyboardWillShow;
private NSObject keyboardWillHide;
private double duration;
private UIViewAnimationCurve curve;
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.keyboardWillShow = UIKeyboard.Notifications.ObserveWillShow(this.KeyboardWillShow);
this.keyboardWillHide = UIKeyboard.Notifications.ObserveWillHide(this.KeyboardWillHide);
}
public override void ViewDidDisappear(bool animated)
{
base.ViewDidDisappear(animated);
this.keyboardWillShow.Dispose();
this.keyboardWillHide.Dispose();
}
private void KeyboardWillShow(object sender, UIKeyboardEventArgs args)
{
if (!this.keyboardShowing)
{
this.keyboardShowing = true;
var keyboardFrame = UIKeyboard.FrameBeginFromNotification(args.Notification);
this.duration = args.AnimationDuration;
this.curve = args.AnimationCurve;
this.ScrollTheView(true, keyboardFrame.Height);
}
}
private void KeyboardWillHide(object sender, UIKeyboardEventArgs args)
{
if (this.keyboardShowing)
{
this.keyboardShowing = false;
var keyboardFrame = UIKeyboard.FrameBeginFromNotification(args.Notification);
this.duration = args.AnimationDuration;
this.curve = args.AnimationCurve;
this.ScrollTheView(false, keyboardFrame.Height);
}
}
private void ScrollTheView(bool scale, nfloat scrollAmount)
{
UIView.BeginAnimations(string.Empty, IntPtr.Zero);
UIView.SetAnimationDuration(this.duration);
UIView.SetAnimationCurve(this.curve);
var frame = View.Frame;
// Assumes the page belongs to a tabbed view.
// This does not scale to pages that do not have one.
UITabBarController tabBarController = new UITabBarController();
nfloat tabHeight = tabBarController.TabBar.Frame.Size.Height;
scrollAmount -= tabHeight;
if (scale)
{
frame.Y -= scrollAmount;
}
else
{
frame.Y += scrollAmount;
}
View.Frame = frame;
UIView.CommitAnimations();
}
}
There is two issues in your approach
After Task.Delay(10), you are not on the UI thread anymore, which means you have to use Device.BeginInvokeOnMainThread in order to access UI elements.
Control.ShouldEndEditing must be cleared before you call EndEditing
A working solution would look like this:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Element == null || Control == null)
return;
VisualElement element = Element as VisualElement;
if (element == null)
return;
if (e.PropertyName == VisualElement.IsFocusedProperty.PropertyName && element.IsFocused == false)
{
Control.ShouldEndEditing = (UITextView control) =>
{
Device.BeginInvokeOnMainThread(() =>
{
control.ShouldEndEditing = null;
control.EndEditing(true);
});
// prevent the keyboard from closing
return false;
};
}
}
I am getting a problem transfering the text from an EditText to a TextView (I have also tested transfering it to an EditText with the property enable set to false) and it works OK on the emulator but when I test it on the real device, it always crashes when it attempts to set the text.
I have also tested sending just a text (see commented line) with the same result
EditText editText = (EditText) findViewById(R.id.Texte);
editText.setOnEditorActionListener(new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView arg0, int arg1, KeyEvent arg2)
{
int A;
boolean handled = false;
if (arg2.getKeyCode() == KeyEvent.KEYCODE_ENTER)
{
TextView Etiqueta = (TextView)findViewById(R.id.textView1);
Etiqueta.setText(arg0.getText().toString());
//Etiqueta.setText("40");
handled = true;
}
return handled;
}
});
I have found another way using the onKeyListener that don't gives error
#Override
public boolean onKey(View view, int keyCode, KeyEvent event)
{
TextView Etiqueta = (TextView)findViewById(R.id.textView1);
TextView Etiqueta2 = (TextView)findViewById(R.id.textView2);
EditText myEditText = (EditText) view;
if ( event.getKeyCode() == KeyEvent.KEYCODE_ENTER)
{
if (!event.isShiftPressed())
{
//Log.v("AndroidEnterKeyActivity","Enter Key Pressed!");
switch (view.getId())
{
case R.id.Texte:
Etiqueta.setText(myEditText.getText());
break;
case R.id.Texte2:
Etiqueta2.setText(myEditText.getText());
break;
}
return true;
}
}
return false;
}
I want to show the virtual keyboard when the user is editing the textfield. I take this approach :
public class ChpModif extends TextField {
public ChpModif(int maxChars, FocusListener focusListener, DataChangedListener dataChangeListener, VirtualKeyboard vkb)
{
super();
setReplaceMenu(false);
if (maxChars != -1)
setMaxSize(maxChars);
addFocusListener(focusListener);
addDataChangeListener(dataChangeListener);
if (vkb != null)
VirtualKeyboard.bindVirtualKeyboard(this, vkb);
}
protected Command installCommands(Command clear, Command t9)
{
return null;
}
}
public class ModifierFicheClient extends Ecran implements ActionListener, DataChangedListener, FocusListener
{
private VirtualKeyboard vkNombre = new VirtualKeyboard();
private String textFieldStatus, listBoxStatus;
private ListBox genretxt;
private boolean modifFromUpdate;
private ChpModif nomtxt,prenomtxt,cintxt,adressetxt/*,genretxt*/,lieutxt,professiontxt,courieltxt,teltxt,datenaisstxt;
private Component cursorItem;
...
public ModifierFicheClient(SmartPhoneBanking controller,String prosp_id,int recordStoreID,Form prevForm)
{
super("");
vkNombre.setInputModeOrder(new String[]{VirtualKeyboard.NUMBERS_SYMBOLS_MODE});
...
modifFromUpdate = false;
cintxt = new ChpModif(12, this, this, vkNombre);
...
}
public void dataChanged(int type, int index) {
textFieldStatus = "CHANGED";
if (!modifFromUpdate)
{
try
{
if (type == DataChangedListener.ADDED || type == DataChangedListener.CHANGED || type == DataChangedListener.REMOVED)
{
if (Display.getInstance().isVirtualKeyboardShowingSupported())
{
if (!Display.getInstance().isVirtualKeyboardShowing())
cursorItem.pointerReleased(cursorItem.getAbsoluteX(), cursorItem.getAbsoluteY());
}
}
}
catch (ClassCastException cce)
{}
}
}
public void focusGained(Component chp) {
cursorItem = chp;
}
public void focusLost(Component arg0) {
}
protected void onShowCompleted()
{
...
update();
}
public void update()
{
modifFromUpdate = true;
cintxt.setText(fichesignalitique.elementAt(0).toString());
...
modifFromUpdate = false;
}
...
}
The problem is that at the first time when I edit the textfield then the virtualkeyboard is shown ; then I click the Ok button of the virtualkeyboard , and then I edit again the textfield. But in this time the virtualkeyboard is not shown !
So how to make the virtualkeyboard shown everytime I edit the textfield ?
Its entirely possible that this is a 1.4 bug that was fixed in 1.5 since I can't see it right now. The VKB was brand new in 1.4 .