I have an activity which has a fragment. Inside that fragment, there are 5 fragmnets inside ViewPager. Each fragment has either more than 30 input fields including EditTexts, custom Dropdowns and Date Pickers or nested ViewPagers with fragments having same amount of input fields.
The problem is; when user taps on any EditText to input data, soft keyboard gets visible and when it is completely visible, the app freezes for around 2 seconds. When user presses back button to hide soft keyboard, keyboard gets off from screen and screen area which is underneath soft keyboard becomes white and app freezes again for same amount of time. This happens every time. Here is activity configuration from manifest:
<activity
android:name=".activities.HomeActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustPan|adjustResize" />
I have tried different combinations for android:windowSoftInputMode nothing worked. Although this does not happen in other activities with same manifest configuration and with less number of fields. With so many input fields, its very annoying for user that app freezes after inputting data in textfields. Can anyone suggest me workaround for this?
I have found the solution. In most of the layouts, the views were aligned vertical to each other inside RelativeLayout using android:layout_below property like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--nested form view containers-->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/layout1"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--nested form view containers-->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/layout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/layout2"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--nested form view containers-->
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
I replaced root RelativeLayouts with vertical oriented LinearLayouts and it did the magic trick like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--nested form view containers-->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--nested form view containers-->
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/layout3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--nested form view containers-->
</RelativeLayout>
</LinearLayout>
</LinearLayout>
I am still looking for some technical details on how it impacts keyboard visibility states. Will update here if I find something.
I will need to hands-on debug to find the issue, but what I think I will do is:
Check whether this is actually because of those many fragments and input controls. Can you try with only 1 fragment instead of 5 fragments and see if the speed improves? If yes, then try to display a fragment at once (ex: if you change from tab 1 to tab 2, explicitly remove fragment 1 from the pager view hierarchy and explicitly add fragment 2 to the pager view hierarchy). If after you simplify your controls, you still see the freeze, then that might not be because of too many controls.
Check whether there is offending control(s).Maybe you have a control or two that unexpectedly do a routine that heavily taxed your resources. If from point #1 you can find a fragment that significantly slowing down your app when it gets displayed, you might want to check further into that fragment and controls inside.
Related
Sorry for the elementary question but I can't find the solution:
When covering a button with a layout without elevation, it emerges over the layout because a button has a depth (negative depth, it points at the viewer).
So, if you have a
<FrameLayout... >
<Button.../>
<FrameLayout
id="#+id/fragmentsContainerOrAnything"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C00F"
android:clickable="true"
android:focusable="true"
>
</FrameLayout>
</FrameLayout>
The button would show through the FrameLayout.... In this case, literally "out of the blue" because the button has depth and so it emerges over the layout, even though the layout is placed "upon" the button.
The question is:
How do I make the FrameLayout cover the underlying Button without fiddling with its elevation.
How do I make the button flat? Of course I can just set it back to the origins and call it "TextView". But is there a nicer way?
Thanks
Add your button inside FrameLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C00F"
android:clickable="true"
android:focusable="true" />
</FrameLayout>
In my app, there is a tabbed activity with three fragments. The first fragment has a form to create a new task, the second fragment has the list of all the saved tasks, and the third fragment will show the comments on a task when selected from the list in the second fragment. The third fragment is also supposed to act like a chat activity which posts comments when you type them in and tap the send button. The XML layout of this third fragment is as follows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:orientation="vertical"
tools:context="com.example.ishita.assigntasks.CommentsFragment">
<TextView
android:id="#+id/frag_task_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#dd55ff"
android:padding="10dp" />
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:transcriptMode="normal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#android:color/white">
<EditText
android:id="#+id/frag_msg_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:layout_weight="1" />
<ImageButton
android:id="#+id/frag_send_btn"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="#android:color/background_light"
android:contentDescription="#string/send_btn"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
</LinearLayout>
As you can see, there is a TextView and a ListView and below that is another LinearLayout. Here is how it should look (the purple bar is the TextView):
And here is how it actually looks:
The TextView shows up above the ListView, but the LinearLayout does not. It is there, though. If I do android:layout_marginBottom="20dp" on the outermost LinearLayout, it does show up, but the ActionBar scrolls up and overlaps with the notification bar so that the title on the ActionBar and the notifications on the notification bar are both visible simultaneously and neither is legible.
I searched a lot and this seemed a common issue, but none of the solutions helped me. Believe me, I tried everything I could find. I tried wrapping the whole thing in a FrameLayout, using a RelativeLayout in place of the outermost LinearLayout, using two LinearLayouts--one to wrap the TextView and the ListView and the other to wrap the EditText and the ImageButton, etc., but nothing was able to show the bottom LinearLayout below the ListView. I even tried to set focus on the EditText when the fragment launches so that the keyboard would show and I can type, but even that doesn't help.
Note: On the other hand, if I use the exact same layout on an activity, the bottom LinearLayout displays exactly as it should.
I am unable to find the bug. Please help!
It looks like your toolbar pushes fragment layout down without decreasing its height. I have no idea why this happens (there are no root layout code here).
As a workaround you can set fragments layout bottom margin to ?attr/actionBarSize
As you have given layout_weight 1 in listview layout, so it occupies the whole space available. In order to get rid of you have to give some static height or use layout_weight in right manner
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="500dp"
android:transcriptMode="normal" />
or try like this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
android:orientation="vertical"
tools:context="com.example.ishita.assigntasks.CommentsFragment">
<TextView
android:id="#+id/frag_task_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#dd55ff"
android:padding="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:background="#android:color/white">
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transcriptMode="normal" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:background="#android:color/white">
<EditText
android:id="#+id/frag_msg_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:layout_weight="1" />
<ImageButton
android:id="#+id/frag_send_btn"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="#android:color/background_light"
android:contentDescription="#string/send_btn"
android:src="#android:drawable/ic_menu_send" />
</LinearLayout>
</LinearLayout>
All,
Thank you for all your responses. I found a workaround by trial and error now and thought I should post the answer for others who face the same issue. I set android:layout_marginBottom="50dp" on the inner LinearLayout (the one wrapping the comments bar--EditText and ImageButton). Somehow, this sets the layout correctly and the fragment functions properly in both Lollipop and Jellybean OS's. I haven't tested on other OS versions.
First of all you should read this, what is layout_weight and how it works.
You assigned layout_weight to ListView as 1, it means it covers whole height. just change it to 0.7 or any proportion you want (less than 1) will solve the problem.
<ListView
android:id="#+id/frag_comment_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.7"
android:transcriptMode="normal" />
Our app's main content is a RecylerView of CardView's. For signup we require more than just a username/password to create an account so we decided to make the signup flow out of CardView's to match the user experience once they sign up.
To do that I have a single Activity that animates fragments in from the bottom and existing fragments out the top to emulate scrolling. This fake scrolling occurs when the user enters data and hits next to advance. This works pretty well except for one case. When we have a EditText for input the keyboard comes up and covers the 'next' button on the bottom of the screen.
In our user testing we've noticed a high percentage of users trying to scroll the card up to get to the next button instead of dismissing the keyboard.
I've spent a lot of time unsuccessfully trying to get the CardView to scroll up to reveal the button and I'm out of ideas and looking for new ones.
The signup Activity layout only contains a FrameLayout that I load Fragments into. Each fragment that gets loaded has a CardView for the root layout.
In the manifest I have set the activity's windowsSoftInputMode to adjustResize, adjustPan with little success.
activity_signup.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/signUpContent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
simplified fragment_enter_code.xml
<android.support.v7.widget.CardView
style="#style/CardViewStyle.SignUp"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="25dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true"
app:contentPadding="8dp">
<EditText
android:id="#+id/codeEditText"
style="#style/HintedEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Code"
android:inputType="text"/>
<Button
style="#style/NextButton"
android:id="#+id/nextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="#string/next"/>
</android.support.v7.widget.CardView>
When I tried putting the CardView in a ScrollView the cardview layout (with fillViewport true), I get a scrollbar but the card doesn't scroll and the cardview layout gets messed up.
Does anyone know the windowSoftInputMode's well enough to point me in the right direction? Or is the CardView just not going to scroll outside of a Container that is design to hold them?
It feels like the solution to this is in manipulating the activity's view not the fragments.
I ended up creating a new app to just play around with this issue and noticed that if I had a layout that didn't contain a CardView whose root layout was a ScrollView it didn't scroll unless the activities windowSoftInputMode is set to adjustResize and then it will scroll.
I then made a layout with a <ScrollView><CardView><content...></CardView></ScrollView> and the size of the CardView was always the default row size for a card and wouldn't match_parent. I solved that with fillViewPort="true" on the ScrollView but when the keyboard came up it wouldn't scroll.
Turns out the secret sauce was to put a FrameLayout (or anyother layout) in between the CardView and the ScrollView.
You still have to account for the resize of the Layout to prevent your view elements not stacking over each other but Once you do that you now get the view above the soft keyboard to scroll and the ability to reach the rest of the UI with a CardView.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fillViewport="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="35dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true"
app:contentPadding="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="#drawable/common_ic_googleplayservices"/>
<EditText
android:id="#+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_below="#id/image"
android:hint="Input"
android:inputType="text"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/input"
android:orientation="vertical"
android:gravity="bottom|center_horizontal">
<Button
android:id="#+id/nextButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:enabled="false"
android:text="Next"/>
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
</ScrollView>
I've got a layout that looks like first image and when I open the softkeyboard looks like the second image, but I want it how it seems on third image:
I read a lot about adjustpan and adjustresize on the manifest but nothing works, the xml structure is:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blanco"
android:gravity="top"
android:orientation="vertical"
android:weightSum="10" >
<!-- LOGO -->
<LinearLayout
android:id="#+id/logo"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3.7"
android:background="#color/green_logo"
android:orientation="vertical"
android:gravity="center"
android:paddingTop="65dp" >
<ImageView
android:id="#+id/logo_registro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:src="#drawable/logo_registro" />
</LinearLayout>
<FrameLayout
android:id="#+id/contentFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6.3" >
</FrameLayout>
</LinearLayout>
First part is the green part with the app logo and inside the FrameLayout I put Fragments that contains simple LinearLayouts or RelativeLayouts with parts of my Login forms.
Put this on your Manifest, inside the activity
<activity android:name=".YourActivity"
android:configChanges="keyboard|keyboardHidden"></activity>
Set your windowSoftInputMode in your manifest for this activity to be adjustResize. THere are 3 possible settings for this- nothing, resize (shrinks your app to fit the remaining space), and pan (scrolls your app so the focused field remains on screen).
Just Add the empty scrollview and it will work
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
</ScrollView>
I have two layouts within a fragment that I switch back and forth between by making one invisible and the other visible and visa versa. When the layout that contains an EditText becomes visible the soft keyboard automatically pops up. I have used the following in the manifest but it didn't help.
android:windowSoftInputMode="stateUnchanged"
I never explicitly request focus on the EditText and have even tried requesting focus on something else to no avail.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:id="#+id/container">
<LinearLayout android:id="#+id/dial_pad_ll"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:layout_centerInParent="true"
android:background="#1E1E1E" android:layout_marginLeft="20dp" android:layout_marginRight="20dp">
<EditText android:layout_height="wrap_content" android:id="#+id/search_et"
android:layout_width="match_parent" android:layout_alignParentTop="true"
android:layout_marginTop="20dp" android:layout_marginBottom="10dp" >
</EditText>
<!-- Other widgets here -->
</LinearLayout>
<!-- Other Layout Here -->
</RelativeLayout>
Anyone know how to prevent this? Thanks.
Edit: I should also have mentioned that this doesn't happen the first time. I open layout 1 with the edit text, make it invisible, make it visible again, then the keyboard pops up.
try adding this to your activity.
this.getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);