Scroll the screen up when keyboard appears - android

I have an activity with an editText in the middle. When I click on the
editText the keyboard appears, and the screen moves so that the
editText is just above the keyboard, covering the other stuff that is
below.
I don't want to resize or add padding to the layout. I need that
the screen scrolls to the top the amount of space that I need to see
also the other stuff below. In other words, I'd like to select the
position of the editText when the keyboard appears. It would be enough
also if the screen scrolls up completely, showing me the bottom of the
layout.
I tried to put the layout in a scrollView adding this code on the editText
editText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//make the view scroll down to the bottom
scrollView.scrollTo(0, scrollView.getBottom());
}
});
but it doesn't work. Does anyone have an idea? Thank you in advance!

use android:windowSoftInputMode="adjustPan"
"adjustResize"
The activity's main window is always resized to make room for the soft keyboard on screen.
"adjustPan"
The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.
For example inn your manifest file:-
<activity
android:windowSoftInputMode="adjustPan"
android:name=".MainActivity"></activity>
Late answer.But surely it helps anyone.

I had a similar problem once, I resolved using:
android:windowSoftInputMode="adjustResize"
in the AndroidManifest.xml.
If you use a RelativeLayout start with the bottom element that must be hooked to the parent bottom and then hook the other element above the previous.
If you use LinearLayout wrap it in a RelativeLayout and hook the LinearLayout to parentBottom.
In this way when the keyboard pops up you will see the bottom of your layout.
Hope this helps.

I had a this problem , I resolved by this code :
myEdittext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myscrollview.postDelayed(new Runnable() {
#Override
public void run() {
View lastChild = myscrollview.getChildAt(myscrollview.getChildCount() - 1);
int bottom = lastChild.getBottom() + myscrollview.getPaddingBottom();
int sy = myscrollview.getScrollY();
int sh = myscrollview.getHeight();
int delta = bottom - (sy + sh);
myscrollview.smoothScrollBy(0, delta);
}
}, 200);
}
});

This works for me
android:windowSoftInputMode="stateVisible|adjustResize"
in androidmanifest for the activity

This works: -
There is an issue with the scroll up when Keyboard opens up in Constraint Layout.
Don't use that.
To achieve "Scroll the screen up when keyboard appears"
Try this
Use Linear layout and ScrollView
and fill_parent in Scroll view.
and any Text field in the scroll view.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true">
</ScrollView>
</LinearLayout>

Add this library to your gradle dependencies:
dependencies {
compile 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:2.1.0'
}
and use this code:
KeyboardVisibilityEvent.setEventListener(getActivity(), new KeyboardVisibilityEventListener() {
#Override
public void onVisibilityChanged(boolean isOpen) {
if (isOpen && MY_EDIT_TEXT.hasFocus()) {
//scroll to last view
View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
int sy = scrollLayout.getScrollY();
int sh = scrollLayout.getHeight();
int delta = bottom - (sy + sh);
scrollLayout.smoothScrollBy(0, delta);
}
}
});

It only worked for me after I changed from Constraint Layout to Linear Layout and added
android:windowSoftInputMode="adjustResize".
and removed
<item name="android:windowFullscreen">true</item> from the Activity style

just add
android:screenReaderFocusable="true"
to your XML file, it will work like a charm

The simple way to do it in Kotlin (reused from user user6581344 's answer), and i used it to perform a manual scroll to EditText when focus is set and keyboard is shown, as need it with extra bottom padding between keypad and the EditText:
binding.scrollView.postDelayed(object:Runnable {
override fun run() {
val extraBottomPadding = 100
val manualScroll = txtFullName.y + extraBottomPadding
scrollView.smoothScrollBy(0, manualScroll.toInt())
}
}, 200)

This code works for me, no need to add clickListener() or focusChanhgeListener() in your activity override onUserInteraction() function
#Override
public void onUserInteraction() {
super.onUserInteraction();
if (editText.hasFocus() ) { // to check if user is clicked on edit text
if (scroll.getVerticalScrollbarPosition() != scroll.getBottom()) // if scrollview is not already on the bottom
scroll.post(() -> scroll.scrollTo(0, scroll.getBottom()));
}
}

Related

How to hide footer component that appear on keyboard's top when editText gets focused in fragment?

Fragment layout
Actually the footer is set inside an activity class and the edittext is placed inside a fragment.
manifest file
<activity
android:name="HomeController"
android:label="#string/app_name"
android:windowSoftInputMode="stateHidden|adjustPan"/>
Inside my fragment class I added
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
These are the code snippet that I used, but it won't work!
Note: in Fragment UI, the whole screen has a scroll view,
Don't know why it is happening like this?Actually I don't want my footer on the keyboard's top.
Any suggestions on how to solve this behavior? And its appriciatble for the replies :)
Add this to your activity.
I did not test, but this might work. it is a bad way though(
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
View rootView = getWindow().getDecorView().getRootView();
rootView.getWindowVisibleDisplayFrame(r);
int screenHeight = rootView.getHeight();
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
int keypadHeight = screenHeight - r.bottom;
Log.d(TAG, "keypadHeight = " + keypadHeight);
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
// keyboard is opened
//set bottom navigation(footer) bar to View.GONE
}
else {
// keyboard is closed
//set bottom navigation bar(footer) to View.VISIBLE
}
}
});
Use android:windowSoftInputMode="hidden" in your parent layout in the xml file. also in case it has layoutAbove property then try to remove it.
Try to add the following in manifest file:
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
Also remove the following from fragment:
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Why does the fragment get padding on top and bottom when it resizes when the keyboard is shown?

I have an activity that hosts a fragment, and several others.
This activity already has fitsSystemWindows=false so that it will extend it's boundaries towards the very bottom of the screen, I am hiding the Navigation Bar btw.
The problem is, it has a fragment that has a RichEditor view inside it which means users should be able to put multiple lines of text inside that fragment. SO I made that fragment fitsSystemWindows=true so that when users start clicking on the RichEditor and types, the adjustResize flag, which I have set in the styles, will fire up and allow the user to scroll the page.
It resizes and allows the user to scroll yes.
The only problem is, when the fragment resizes, it gets additional padding on the top and bottom and since I have a custom toolbar on the main activity, it is very awkwardly visibly being added on screen. The funny thing is, the top padding is exactly the same as the height of the device's status bar and the bottom padding is exactly the same as the height of the Navigation Bar.
I tried making the clipToPadding attribute in the fragment's layout into true and false but it does not stop the fragment from getting the additional paddings. I also searched around but I can't get anything useful to get around this as most of the questions I encounter are about how to ALLOW the resize to happen and not anything about how to remove or stop the padding.
Is there even any way to know when the fragment has been resized or the resize has been triggered? If ever I can use that listener to remove the additional paddings as needed.
Any thoughts on this?
EDIT
I already tried putting fitsystemwindows=true in the main activity, but it gets some padding on the bottom for the navigation bar. And I need the activity to fill the whole screen as the navigation bar is hidden
I have solved this by following Matej Snoha's comment. This method attaches a listener to the fragment and when it sees the heightDifference, which is the size of the keyboard as well, is more than the height of the navigation bar, it puts a padding to the bottom of the view thus allowing it to scroll while the keyboard is open.
public class FragmentResizeUtil {
public static void setListenerforResize(final View root, Fragment fragment) {
final int navigationbarHeight = getNavigationBarHeight(fragment);
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
Rect r = new Rect();
root.getWindowVisibleDisplayFrame(r);
int screenHeight = root.getRootView().getHeight();
int heightDifference = screenHeight - (r.bottom - r.top);
if (heightDifference > navigationbarHeight) {
root.setPadding(0, 0, 0, heightDifference);
} else {
root.setPadding(0, 0, 0, 0);
}
}
});
}
private static int getNavigationBarHeight(Fragment fragment) {
Resources resources = fragment.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
return resources.getDimensionPixelSize(resourceId);
}
return 0;
}
}

Adjust scroll position when soft keyboard opens

I have a form within a ScrollView. When I tap into an EditText the soft keyboard appears and the ScrollView scrolls the now focused EditText so that it just comes into view.
However, I have hint information just below the EditText that I also would like to show, so the scrolling should go just a bit further up, like this:
The EditText is embedded in a form element and actually I'd like to scroll to the bottom of that. I've checked the source code of ScrollView and it will just scroll to the bottom of the currently focused view. Maybe there's a way to tell the ScrollView that the form element is the currently focused element?
Of course I could write my own ScrollView sub class and override the scroll behavior, but I wonder if there's a more elegant way of doing this.
Any other suggestions (with adjust scrolling with a fixed offset or so) are also appreciated.
I have not really found any way to configure the scrolling behavior of the ScrollView from the outside. So I ended up to define my own sub class of ScrollView:`
/**
* {#link ScrollView} extension that allows to configure scroll offset.
*/
public class ConfigurableScrollView extends ScrollView {
private int scrollOffset = 0;
public ConfigurableScrollView (final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public void setScrollOffset (final int scrollOffset) {
this.scrollOffset = scrollOffset;
}
#Override
protected int computeScrollDeltaToGetChildRectOnScreen (final Rect rect) {
// adjust by scroll offset
int scrollDelta = super.computeScrollDeltaToGetChildRectOnScreen(rect);
int newScrollDelta = (int) Math.signum(scrollDelta) * (scrollDelta + this.scrollOffset);
return newScrollDelta;
}
}
computeScrollDelta(...) is the only protected method that can be targeted for overriding, apart from onSizeChanged(...).
The signum function in the example above ensures that scrolling is only increased, if the ScrollView really thinks that scrolling is necessary (e.g. when keyboard pops up).
I can now set the extra scroll offset once from the outside, as calculated from the height of the hint.
It's not hard to use the extended ConfigurableScrollView instead of the standard ScrollView, I only had to replace the ScrollView XML tag with the FQN of the new class.
Considering that you are using ScrollView you have the possibility to use the method ScrollTo as follow:
scrollView.post(new Runnable() {
#Override
public void run() {
sv.scrollTo(x-value, y-value);
}
});
where the first argument is the scroll value for X, while the second argument is the scroll value for Y. So you just have to set your scrollView offset when the keyboard is displayed.
Hope it helps;)

Android: call requestLayout() after update v.layout parameter causes layout reverts back to it's original position

I have framelayout which contains two relative layouts, one is on top of the other. When user clicks a button, the one on the top move 80% off the screen to the right. Then one on the bottom becomes clickable. This is what it looks like.
FrameLayout
RelativeLayout (bottom) RelativeLayout (top)
FilterWidgets Open/close button, ListView
It's really easy to achieve on 3.0+ with the new animation api which is Property base Animation. For the pre 3.0, because animation is view based. So I end up manually modify the layout property on onAnimationEnd. The call requestLayout to make it permanent, but only to find out the layout reverts back to original position. Anybody know how to move layout permanently?
see my other post if you want to see the whole picture:
https://stackoverflow.com/questions/14541265/changecursor-cause-layout-container-of-the-listview-to-reposition
theTranslationX.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator nullPointer) {
v.clearAnimation();
int theL = isMenuOn() ? 0 : v.getLeft() + getFilterWidth();
int theR = isMenuOn() ? v.getWidth() : v.getLeft() + getFilterWidth() + v.getWidth();
int theHeight = v.getHeight();
int theT = 0;
v.layout(theL, theT, theR, theHeight);
v.requestLayout();
}
});
This is 9 months late but try using:
yourView.layout(left,top,right,bottom); //all parameters are type int
However I don't think this is permanent, the position of the view will still be reset when you call requestLayout(), but give it a try.

Android Move the whole screen upwards when softkeypad is opened?

i just want to shift my whole activity screen upwards when the user clicks on the edit text...
i mean the screen will shift upwards and below it we can see the soft keypad...
I have tried using android:windowSoftInputMode="adjustPan|adjustResize" in my Manifest file but it doesn't make any sense..
thanks in advance ...
In your xml layout. Make the scrollview to be root parent, and it will work!
Try this to detect if keyboard is up, and then scroll down (you need your scroll to be root in xml):
final View activityRootView = findViewById(R.id.scroll);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
//keyboard is visible
if (heightDiff > 100) {
scroll.fullScroll(ScrollView.FOCUS_DOWN);
}
}
});

Categories

Resources