B4A Library IME library (soft keyboard)

manios

Active Member
Licensed User
Longtime User
This Lib is really helpfull!:sign0098:
 

Lon

Member
Licensed User
Longtime User
I can't seem to get any of the IME library features to work. The IDE shows IME(version 1.00) checked off.
I have tried all the code examples in the "Handle the soft keyboard with the IME library" post. But nothing works.
Can someone show me a full example in case I'm just missing something basic? Is it possible that the library isn't loaded correctly? Thanks.

Never mind... I had not initialized the IME object first.
 
Last edited:
D

Deleted member 103

Guest
Thank you for this library, I can really use it very well.
:sign0098:
 

JesseW

Active Member
Licensed User
Longtime User
A little helpful info concerning the HeightChanged event: the NewHeight parameter is the height of the now available part of the screen, not the new height of the keyboard itself.
 

Vinians2006

Active Member
Licensed User
Longtime User
Hi Erel, Im trying to use the IME library but its asking me for a password. What password should I put ?
 

Roger Garstang

Well-Known Member
Licensed User
Longtime User
Is there source code for the IME Library anywhere...or if not how likely would it be? I'm creating a Relative Layout library to do what my View Manager Class did and more. I used the IME library a lot in it and would like to do a lot of the stuff internal to the library like Setting up the Input Types, Character Filters, Action Buttons, handling/passing Action Button Events, etc.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Here is the code:
B4X:
package anywheresoftware.b4a.objects;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.text.method.NumberKeyListener;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BALayout;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.BALayout.LayoutParams;
import anywheresoftware.b4a.keywords.Common;

/**
 * IME includes several utilities that will you help you manage the soft keyboard.
 *A tutorial with a working example is available <link>here|http://www.b4x.com/forum/basic4android-getting-started-tutorials/14832-handle-soft-keyboard-ime-library.html</link>.
 */
@ShortName("IME")
@Events(values={"HeightChanged (NewHeight As Int, OldHeight As Int)",
      "HandleAction As Boolean"})
@Version(1.0f)
@ActivityObject
public class IME {
   private String eventName;
   /**
    * Initializes the object and sets the subs that will handle the events.
    */
   public void Initialize(String EventName) {
      this.eventName = EventName.toLowerCase(BA.cul);
   }
   /**
    * Hides the soft keyboard if it is visible.
    */
   public void HideKeyboard(BA ba) {
      InputMethodManager imm = (InputMethodManager)BA.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE);
      imm.hideSoftInputFromWindow(ba.vg.getWindowToken(), 0);
   }
   /**
    * Sets the focus to the given view and opens the soft keyboard.
    *The keyboard will only show if the view has received the focus.
    */
   public void ShowKeyboard(View View) {
      View.requestFocus();
      InputMethodManager imm = (InputMethodManager)BA.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE);
      imm.showSoftInput(View, 0);
   }
   /**
    * Adds the HandleAction event to the given EditText.
    */
   public void AddHandleActionEvent(final EditText EditText, final BA ba) {
      EditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {

         @Override
         public boolean onEditorAction(TextView v, int actionId,
               KeyEvent event) {
            Boolean b =  (Boolean)ba.raiseEvent(EditText, eventName + "_handleaction");
            if (b != null && b == true)
               return true;
            else
               return false;
         }
         
      });
   }
   /**
    * Sets a custom filter.
    *EditText - The target EditText.
    *DefaultInputType - Sets the keyboard mode.
    *AcceptedCharacters - The accepted characters.
    *Example: Create a filter that will accept IP addresses (numbers with multiple dots)
    *<code>
    *IME.SetCustomFilter(EditText1, EditText1.INPUT_TYPE_NUMBERS, "0123456789.")</code>
    */
   public void SetCustomFilter(EditText EditText, final int DefaultInputType, final String AcceptedCharacters) {
      EditText.setKeyListener(new NumberKeyListener() {

         @Override
         protected char[] getAcceptedChars() {
            return AcceptedCharacters.toCharArray();
         }

         @Override
         public int getInputType() {
            return DefaultInputType;
         }
         
      });
   }
   /**
    * Enables the HeightChanged event. This event is raised when the soft keyboard state changes.
    *You can use this event to resize other views to fit the new screen size.
    *Note that this event will not be raised in full screen activities (an Android limitation).
    */
   public void AddHeightChangedEvent(BA ba) {
      if (ba.vg.getParent() instanceof BALayout)
         return;
      ExtendedBALayout e = new ExtendedBALayout(ba.context, eventName, ba);
      ba.activity.setContentView(e);
      BALayout.LayoutParams lp = new BALayout.LayoutParams();
      lp.height = ba.vg.getLayoutParams().height;
      lp.width = ba.vg.getLayoutParams().width;
      ba.vg.setLayoutParams(lp);
      e.addView(ba.vg);
      ba.activity.getWindow().setSoftInputMode(ba.activity.getWindow().getAttributes().softInputMode | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
   }
   
   static class ExtendedBALayout extends BALayout {
      private int lastHeight = -1;
      private final String eventName;
      private final BA ba;
      public ExtendedBALayout(Context context, String EventName, BA ba) {
         super(context);
         this.eventName = EventName.toLowerCase(BA.cul);
         this.ba = ba;
      }
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int height = MeasureSpec.getSize(heightMeasureSpec);
         if (height != lastHeight && lastHeight != -1) {
            ba.raiseEvent(null, eventName + "_heightchanged", height, lastHeight);
         }
         lastHeight = height;
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);       
      }

   }

}

Note that as a general rule it is better to implement everything in B4A code except things that must be implemented in the library.
 

RadCoder

Member
Licensed User
Longtime User
thanks for posting that, as a result i traced down a bug I was experiencing with the heightChanged event. Because its declared as a static java class, using the IME lib encapsulated within mutiple B4a classses is not good. Basically the IME event will fire the height changed event to the first instance of IME. Weird stuff but makes sense.

You may ask why im doing that in the first place, I have created a couple of usercontrols which I encapsulated using B4a classes, each control class triggers off of the heightchanged event where needed

Erel you should include this type of behavior in the online B4a docs, again had I not seen the source...
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Because its declared as a static java class, using the IME lib encapsulated within mutiple B4a classses is not good. Basically the IME event will fire the height changed event to the first instance of IME. Weird stuff but makes sense.
This is not correct. Static Java classes are different than static fields. There can be many instances of this class.
 

RadCoder

Member
Licensed User
Longtime User
appreciate the quick response. I understand how static classes work in java, and see your point however I guess I was quick to dismiss the cause of the quirky behavior to the static declaration. Nevertheless it is a bug then, here is how to reproduce:

Create 2 activity classes (class a ,b)

each class instantiates a private IME class instance
each class has its own private edittext instantiated from a class specific designer layout
register the heightchanged handler in each class init

Launch the app
main init class a
class A loads class A layout which has an edittext
click on edittext
softkey pops , private CLASS A heightchanged fired , log entry

click on a button
init class b
class B loads class B layout which has an edittext
softkey pops , heightchanged fired , log entry
softkey pops , LOG shows private CLASS A heightchanged fired

both IME instances are private instances to each class and have different event names, for example
aIME.initialize("CLASSA")
aIME.initialize("CLASSB")
 

RadCoder

Member
Licensed User
Longtime User
ok thanks for what its worth I worked around it with the following:

instantiate ime and the heightchanged event in main
in each class instantiate IME with the same event definition

edittext views within its class once clicked will fire heigtchanged event defined in main

I have the heightchanged event in main callback the appropriate class who's edittext triggered it

not ideal from an encapsulation point of view but works great

hope that helps someone
 

JesseW

Active Member
Licensed User
Longtime User
Erel, I need a way to query the newheight while resuming an activity. say my editor is paused to check an email or something. when it is resumed, I need a way to know how much space I have, as the keyboard may or may not have been visible on the pause, and it may or may not be visible on the resume. this is such a wonderful library. help?

edit: is there a way I can use reflection to access measurespec.getsize?
 
Last edited:
Top