I want to show a button when the virtual keyboard is open and hide this button if the virtual keyboard visibility is off.But I could not find any listeners to perform this activity.
Anybody knows how to do this?
As found here, you'll need to instantiate the SoftkeyBoard and add a listener.
/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use your root layout
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);
/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{
#Override
public void onSoftKeyboardHide()
{
// Code here
}
#Override
public void onSoftKeyboardShow()
{
// Code here
}
});
/*
Open or close the soft keyboard programatically
*/
softKeyboard.openSoftKeyboard();
softKeyboard.closeSoftKeyboard();
/*
SoftKeyboard can catch keyboard events when an EditText gains focus and keyboard appears
*/
/* Prevent memory leaks:
*/
#Override
public void onDestroy()
{
super.onDestroy();
softKeyboard.unRegisterSoftKeyboardCallback();
}
In his post, you will also find more information about bug fixes and possible problems.
add onGlobalLayoutListener to your parent view of activity/fragment and make your button visibility accordingly
final View parentView= findViewById(R.id.myrootview);
parentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = root.getRootView().getHeight() - root.getHeight();
Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int contentViewTop=
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
if(heightDiff <= contentViewTop){
//Soft KeyBoard Hidden---button visible
}else{
//Soft KeyBoard Shown---button hide
}
}
});
There is no direct event for keyboard open and close. but you can create observer on your full layout and then display buttons or whatever you want to do.
For Observer code check this - Hide part of activity_main.xml if keyboard is open (Android)
Related
I have an activity that is basically a long form of entry fields.
On each row, I want to show a TextView to serve as hint text just below each EditText and I want the TextView to remain visible at all times when the user is entering data. Unfortunately, the soft keyboard obscures the hint text and always positions itself immediately below the EditText. Is there any technique that will allow the TextView below the EditText to also be visible when the soft keyboard appears and the contents are adjusted (via windowSoftInputMode=adjustResize|adjustPan), without having the user scroll ?
Vishavjeet got me on the right track in suggesting I scrolldown to reveal the view that may be overlapped by the keyboard. Below is a function similar to what I used to solve the problem. It can be called when the EditText above the TextView receives focus:
// View targetView; // View that may be hidden by keyboard
// ScrollView scrollContainerView; // Scrollview containing hiddenView
//
void assureViewVisible (View targetView, ScrollView, scrollContainerView) {
Window rootWindow = activity.getWindow();
Rect rMyView = new Rect();
View rootview = rootWindow.getDecorView();
rootview.getWindowVisibleDisplayFrame(rMyView); // Area not taken up by keyboard
int subTextPos[] = new int[2];
targetView.getLocationInWindow(subTextPos); // Get position of targetView
int subTextHt = targetView.getHeight(); // Get bottom of target view
if ((subTextPos[1]+subTextHt) > rMyView.bottom) { // Is targetView at all obscured?
int scrollBy = (subTextPos[1]+subTextHt) - rMyView.bottom + 10; // add a small bottom margin
mMeasurementViewScrollView.smoothScrollBy(0, scrollBy); // Scroll to subtext
}
}
EDIT:
By understanding the problem more deeply, I think that you should add scroll programatically when user clicks on the Edittext. Here is the code to do that:
private final void focusOnView()
{
new Handler().post(new Runnable()
{
#Override
public void run()
{
your_scrollview.scrollTo(0, your_EditBox.getBottom());
}});
}
From my personal experience I think there is not such way to do that. The thing you can do is place the hint textview toRightOf the editext. Or Use modern Approach by using a Hint Placeholder on Edittext:
In XML, it's simply android:hint="someText"
Programatically you can use edittext.setHint(int);
pass R.string.somestring in above method.
I've implemented a simple EditText that provides a Done button to hide the keyboard and upon rotating to landscape it does not present a full screen dialog for the EditText. But there's a problem. When I tap Done to dismiss the keyboard then I rotate the device to landscape, the keyboard appears. If I dismiss it again then rotate to portrait the keyboard appears yet again.
How can I preserve the keyboard visibility state upon rotation - if it was hidden before rotation then don't present it after rotation, but if it was visible before rotation then present it after rotation?
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/editText1"
android:inputType="text"
android:imeOptions="flagNoFullscreen|actionDone" />
I tried setting android:descendantFocusability="beforeDescendants" and android:focusableInTouchMode="true" in the parent container (RelativeLayout), but that didn't affect this behavior.
There are two options..
In your onCreate() method try these options
Option 1.
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Option 2
edittext.clearFocus();
This option sets the focus back to the first focusable view in the activity.
EDIT:
Option 2 will not work if your edittext it self is the first focusable view in your activity as clearFocus sets the focus back to first focusable view in your activity.
Usage of Option 1:
public class MyActivity extends Activity {
EditText editText1;
boolean isKeyBoardOpen=false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
editText1 = (EditText) findViewById(R.id.editText1);
if(savedInstanceState!=null &&(savedInstanceState.getBoolean("isKeyBoardOpen",false)))
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
else this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
final View activityRootView = findViewById(R.id.root_layout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
isKeyBoardOpen=true;
}else isKeyBoardOpen=false;
}
});
}
protected void onSaveInstanceState(final Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putBoolean("isKeyBoardOpen",isKeyBoardOpen);
}
}
there are many ways to do but i give you 2
1 overide onConfigurationChange method in there at the time of configuration change see if keyboard is open or not and you can act according by saving the value of it an boolean and after onConfigurationChange is changes use that boolean value to show or hide keyboard.
2 Another way if you have not implemented onConfigurationChange method is saving status in onSaveInstanceState and retrieving it in onRestoreInstanceState like below.
#Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
//get the status of keyboard
boolean status = isKeyboardVisible(){this is your method or your logic};
outState.putBoolean(key, status)
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
boolean status = savedInstanceState.getBoolean(key);
//based on status show or hide keyboard.
}
I have a View say anchor and a PopupWindow pop. pop is shown with showAsDropDown when I click a button on anchor.
What I want is to show pop automatically at the first time anchor comes to screen. So I override onAttachedToWindow and add a onGlobalLayoutListener and show pop in it. see below:
private boolean mFirstRun = true;
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if(mFirstRun) {
mFirstRun = false;
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
showPopup();
getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
}
}
The result is, only the first time (see above) pop will stay right above anchor. I have confirmed the width and height of pop is correct. when the button click triggers, pop is shown at the proper place.
After spending some time I found the problem is in onGlobalLayoutListener anchor.getLocationOnScreen has a larger value than the final value so there's no enough space for pop below it.
How can I fix this? and why the screen location is incorrect in that listener?
I have a layout in which I have autoComplete edit text with some suggestions.
The image below is its normal behaviour until keyboard slides in.
after the keyboard comes the dropdown goes above the field which hides my TO: field. As shown below.
What should I do to get the dropdown below even when the keyboard slides up.
I want the result to be like this.
Thanks...
I resolved this by hiding the upper layout when key board is shown and focus is on this edit text. As soon as the keyboard is slided_out the upper layout is visible again which bring back the original screen.
For detecting the keyboard slide_in/slide_out i used something like this.
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView()
.getHeight() - activityRootView.getHeight();
if (heightDiff > 100) { // if more than 100 pixels, its
// probably a keyboard...
if (searchText.isFocused()) {
//keyboard is shown
}
} else {
if (searchText.isFocused()) {
//Keyboard is hidden.
}
}
}
});
Im working on an input method for android and one of the tasks is to implement a custom popup keyboard for hard keyboard key presses. Usually input methods let the editor handle that but the thing is I need to add more symbols than android supports.
So I implemented the popup keyboard and even have it displaying well when a hard key (character key) is long pressed.
The steps I've followed are:
Create popup window.
Inflate a linear layout which contains a keyboardview and a close button and save it to a view object
bind the keyboardview and close buttons to the relevant objects
Create a keyboard for the popup characters and set it as the keyboard for the keyboard view. The keyboard has a column limit of 5.
set the linear layout as the content view for the popup window
Display the popup window
THE ISSUE: If there are multiple rows in the popup keyboard I am only able to select key in the last row for the column. Even if I click on the key in the first row of that column, the key in the last row gets selected.
If anyone could explain why this is happening and how do I fix it, Id appreciate it.
THE CODE:
PopupWindow mPopupKeyboard = new PopupWindow(this.getBaseContext());
mPopupKeyboard.setBackgroundDrawable(null);
if(mPopupKeyboard != null)
{
this.dismissPopupKeyboard();
View mMiniKeyboardContainer = null;
KeyboardView mMiniKeyboard = null;
View closeButton = null;
mMiniKeyboardContainer = getLayoutInflater().inflate(R.layout.keyboard_popup_keyboard, null);
mMiniKeyboard = (KeyboardView) mMiniKeyboardContainer.findViewById(R.id.popup_keyboardView);
closeButton = mMiniKeyboardContainer.findViewById(R.id.closeButton);
if (closeButton != null)
{
closeButton.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
mPopupKeyboard.dismiss();
});
}
mMiniKeyboard.setOnKeyboardActionListener(this);
String resourcestring = "abcdefghi";
mMiniKeyboard.setKeyboard(new Keyboard(this.getBaseContext(), R.xml.kbd_popup_template, alternates, 3, 0));
mMiniKeyboard.setPopupParent(mCandidateView);
mPopupKeyboard.setContentView(mMiniKeyboardContainer);
mPopupKeyboard.setWidth(LayoutParams.WRAP_CONTENT);
mPopupKeyboard.setHeight(LayoutParams.WRAP_CONTENT);
mPopupKeyboard.showAtLocation(mCandidateView, Gravity.TOP, 0, 0);
}
I had a similar problem with popup keyboards. I found that it was a problem only with Android 2.3. My only workaround was to avoid popup keyboards with more than one row.
The reason this occurs is because KeyboardView sends off the MotionEvent. MotionEvent.getRawX() and getRawY() only return coordinates within the bounds of KeyboardView. If the MotionEvent happens above KeyboardView, it returns the closest absolute coordinates in KeyboardView.
One solution is to create an invisible View above KeyboardView. It will have to detect the MotionEvent and then pass the MotionEvent back to KeyboardView and then your multirow popup keyboard will work
For the starting code look at CandidateViews above the KeyboardView. For example look at this project:
https://github.com/blackcj/AndroidCustomKeyboard
In the
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
(https://github.com/blackcj/AndroidCustomKeyboard/blob/master/app/src/main/java/com/blackcj/customkeyboard/CandidateView.java)
method add 200 to desiredHeight in this statement:
setMeasuredDimension(measuredWidth, resolveSize(desiredHeight, heightMeasureSpec));
Notice how this will cause the motionEvent.getRawY() to work for an extra 200p in height