possible duplicates
Android : autocompletetextview, suggestion list displays above the textview?
I am fully trying to display suggestion list overlapping on keyboard when suggestion list scroll by user but it always open up side.
here I am getting this way
here is my manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sl"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:label="#string/app_name"
android:name=".SuggestionListActivity"
android:windowSoftInputMode="adjustResize|adjustPan|stateHidden">
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
here is my main.xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" android:padding="10dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:layout_margin="10dp"/>
<TextView android:layout_margin="10dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is testing for the auto complete textview in this application to display suggestion list overlapping on keyboard." />
<AutoCompleteTextView android:id="#+id/autocomplete"
android:layout_width="fill_parent" android:layout_margin="5dp"
android:layout_height="wrap_content" android:hint="Search"
android:layout_marginLeft="5dp" android:dropDownHeight="300dp"
android:inputType="textAutoComplete" android:singleLine="true"
/>
</LinearLayout>
what to do in this code to display the suggestion over keyboard when list was focus.
I've had this problem before. For me, there was more screen space above the AutocompleteTextView than below (testing on a "normal" device), so the list opened upwards. I adjusted my layout slightly so that there was more space below the AutocompleteTextView and it started opening downwards. That's what fixed it for me.
You can either adjust the layout so that there is more space below the AutoCompleteTextView
or
you can change the dropdown height android:dropDownHeight and set some high value,
this would work when its inside a scrollView and the AutoCompleteTextView is near the top.
To display the list of options on focus do something like this
autoCompleteTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus) {
autoCompleteTextView.showDropDown();
}
}
});
This would display a list of options when the user focuses on the AutoCompleteTextView
The trick is to ensure that the desired drop-down height is never larger than the available space below. My approach is to create a subclass that overrides showDropDown:
public class DownOnlyAutoCompleteTextView extends AppCompatAutoCompleteTextView {
private final static int MINIMAL_HEIGHT = 50;
public DownOnlyAutoCompleteTextView(Context context) {
super(context);
}
public DownOnlyAutoCompleteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DownOnlyAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void showDropDown() {
Rect displayFrame = new Rect();
getWindowVisibleDisplayFrame(displayFrame);
int[] locationOnScreen = new int[2];
getLocationOnScreen(locationOnScreen);
int bottom = locationOnScreen[1] + getHeight();
int availableHeightBelow = displayFrame.bottom - bottom;
if (availableHeightBelow >= MINIMAL_HEIGHT) {
setDropDownHeight(availableHeightBelow);
}
super.showDropDown();
}
}
Then use this in your layout, e.g.:
<your.package.DownOnlyAutoCompleteTextView
android:id="#+id/auto_complete_text_view"
android:layout_margin="12dp"
android:hint="AutoComplete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="HardcodedText" />
Adjust MINIMAL_HEIGHT to fit your requirements -- if there's no or very little space below, it's probably better not to force the issue.
EDIT
As mentioned in the comments, passing a negative number to setDropDownHeight will trigger an exception in some Android versions. As long as you define a MINIMAL_HEIGHT greater than zero, that should not be a problem.
Here's my solution
private final static int DELAY_MS = 500;
autoCompletionTextView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
autoCompletionTextView.requestFocus();
new Handler().postDelayed(() -> autoCompletionTextView.showDropDown(), DELAY_MS);
return false;
}
});
After keyboard shows up suggestion list is listed above yout AutoCompletionTextView.
use: android:dropDownHeight="wrap_content" in AutoCompleteTextView
Just adding the android:dropDownHeight="100dp" to the AutoCompleteTextView tag in your layout file will be the best solution I guess! it will simply control the height of drop down hight and allow us to scroll!
<AutoCompleteTextView
android:id="#+id/acetxt_assignclient"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:dropDownHeight="100dp">
</AutoCompleteTextView>
I have found if you are using a nested scroll view, it is more prone to open the view above or below as it sees fit where as when you are using a regular scroll view it opens below.
Set Full Layout containing Autocompletetextview inside Scrollview
This will solve your problem!
Related
I'm having problems with the layout of a chat activity on android. I'm doing the tests in a simple application, to make it easier for you to understand.
This is the xml layout:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/constraintMessage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/wallpaper">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
ads:layout_constraintBottom_toBottomOf="parent"
ads:layout_constraintEnd_toEndOf="parent"
ads:layout_constraintStart_toStartOf="parent"
ads:layout_constraintTop_toTopOf="parent">
<ListView
android:id="#+id/listViewMessages"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:paddingTop="7dp" />
<LinearLayout
android:id="#+id/linearLayoutCaixaTexto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="8dp"
android:layout_weight="0"
android:background="#drawable/fundo_mensagem_chat_branco"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="16dp">
<EditText
android:id="#+id/editMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00000000"
android:cursorVisible="true"
android:ems="10"
android:hint="Type here..."
android:imeOptions="actionDone"
android:inputType="textPersonName"
android:linksClickable="true"
android:longClickable="true"
android:maxLength="500"
android:paddingRight="5dp"
android:singleLine="true"
android:soundEffectsEnabled="false"
android:textColor="#android:color/black"
android:textStyle="normal" />
<ImageView
android:id="#+id/imageViewSendMessage"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="8dp"
ads:srcCompat="#drawable/ic_enviar_preto_24dp" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
These are the problems, all with respect to the keyboard:
When you click on EditText, the keyboard opens normally, fast. But when I add items to the listView (so that it fills the entire screen), when clicking on EditText, the keyboard takes a while to open, and also to hide, it gets a little stuck. This is a very annoying problem.
When the keyboard opens, the background in ConstraintLayout is changed, you can see the difference in the images below. I would like the keyboard to be above the background, just like chat apps, when we put a background image of the conversation. The closest I got was putting "adjustNothing" in the windowSoftInputMode, but then the keyboard was over EditText and ListView.
See, if I use "adjustPan" in windowSoftInputMode, this happens:
In short, I would like it to look like this:
The keyboard should open and hide quickly.
EditText must always be above the keyboard (this already happens).
The background image of the conversation should not be changed when opening the keyboard.
I recorded a short video so you can see the problem. Notice in the video that when there are no messages in the listView, the keyboard opens and closes fast, but when there are messages, it is slow, stuck. And also notice the background, when you open the keyboard it is changed. At the end of the video I recorded the same situation in another app, there you can see that the keyboard opens normally and the wallpaper is not changed.
Video: https://www.youtube.com/watch?v=DdMFufZ_Glg&feature=youtu.be
Other codes (if needed):
AndroidManifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.applicationtest">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity"
android:label="Chat"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity:
public class MainActivity extends AppCompatActivity {
private List<Message> listMessages = new ArrayList<>();
private EditText editMessage;
private ImageView imageViewSendMessage;
private MessageAdapter adapterMessages;
private ListView listViewMessages;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editMessage = findViewById(R.id.editMessage);
imageViewSendMessage = findViewById(R.id.imageViewSendMessage);
listViewMessages = findViewById(R.id.listViewMessages);
adapterMessages = new MessageAdapter(listMessages, this);
listViewMessages.setDividerHeight(0);
listViewMessages.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
listViewMessages.setAdapter(adapterMessages);
imageViewSendMessage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!editMessage.getText().toString().isEmpty()) {
Message message = new Message();
message.setM(editMessage.getText().toString());
message.setDm("20/08/2022");
listMessages.add(message);
adapterMessages.notifyDataSetChanged();
}
}
});
}
}
Adapter Class:
public class MessageAdapter extends ArrayAdapter<Message> {
private Context context;
private List<Message> mensagens;
public MessageAdapter(List<Message> list, Context c) {
super(c, 0, list);
this.context = c;
this.mensagens = list;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View listItem = convertView;
Message message = mensagens.get(position);
listItem = LayoutInflater.from(context).inflate(R.layout.adapter_msg_rement,parent,false);
TextView textMensagem;
TextView dataMensagem;
textMensagem = listItem.findViewById(R.id.textMensagemTexto);
dataMensagem = listItem.findViewById(R.id.dataMensagem);
textMensagem.setText(message.getM());
dataMensagem.setText(message.getDm());
textMensagem.setTextColor(Color.parseColor("#000000"));
return listItem;
}
}
ListView attempts to reuse view objects in order to improve performance and avoid a lag in response to user scrolls. To take advantage of this feature, check if the convertView provided to getView(...) is null before creating or inflating a new view object. See Making ListView Scrolling Smooth for more ways to ensure smooth user experience.
As mentioned above you should take care of the performance by using convertView
I'm guessing that's what causing your "little stuck" issues.
As that said I would recommend using RecyclerView
About the background image - you can use adjustPan to push the whole layout above and avoid resizing the image (hope that this is what you wanted...)
Enjoy and Good Luck
I'm trying to adjust the layout when the soft keyboard appears after an edit text gets focus. Right now if I have many edit text and the keyboard appears, the last edit text are hidden and I can't scroll up.
This is how my layout is builded up:
Template:
<LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout>
// header 1
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:orientation="vertical">
// where I inflate view_1
</LinearLayout>
<LinearLayout>
// footer
</LinearLayout>
</LinearLayout>
View (view_1):
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
// ...
</LinearLayout>
<LinearLayout>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
<TextView/>
<EditText/>
</LinearLayout>
</LinearLayout>
</ScrollView>
I already try all kinds of combinations of android:windowSoftInputMode (on manifest.xml and programmatically). I tried to set android:isScrollContainer="false" on the scroll view, but nothing.
I also tried this answer, putting an GlobalLayoutListener in my scroll view, but the onGlobalLayout is not called when the keyboard appears. And the isKeyboardShown is always false.
The best solution I found is to add adjustpan property in the activity<> tag in the manifest.xml file .
<activity
android:name="MyActivity"
android:windowSoftInputMode="adjustPan"/>
I ended up doing it my way.
I created a class that implements OnFocusChangeListener to handle all my EditText:
public class EditTextFocusChangeListener implements OnFocusChangeListener {
private ScrollView scrollView;
public EditTextFocusChangeListener(ScrollView scrollView) {
this.scrollView = scrollView;
}
#Override
public void onFocusChange(View view, boolean hasFocus) {
if(hasFocus) {
int left = view.getLeft();
int top = view.getTop();
int bottom = view.getBottom();
int keyboardHeight = scrollView.getHeight() / 3;
// if the bottom of edit text is greater than scroll view height divide by 3,
// it means that the keyboard is visible
if (bottom > keyboardHeight) {
// increase scroll view with padding
scrollView.setPadding(0, 0, 0, keyboardHeight);
// scroll to the edit text position
scrollView.scrollTo(left, top);
}
}
}
}
Then in the activity, I setted the listener for each edit text:
EditTextFocusChangeListener listener = new EditTextFocusChangeListener(mainScrollView);
editText1 = (EditText) findViewById(R.id.editText1);
editText1.setOnFocusChangeListener(listener);
editText2 = (EditText) findViewById(R.id.editText2);
editText2.setOnFocusChangeListener(listener);
...
editTextN = (EditText) findViewById(R.id.editTextN);
editTextN.setOnFocusChangeListener(listener);
And for the last edit text, I setted an EditorAction listerner to handle the 'Done' button on soft keyboard - to hide the keyboard and put the scroll view back to its original position:
editTextN.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
int result = actionId & EditorInfo.IME_MASK_ACTION;
switch(result) {
// user taped on keyboard DONE button
case EditorInfo.IME_ACTION_DONE:
// put the scroll view back to its original position
mainScrollView.setPadding(0, 0, 0, 0);
// hide keyboard
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
// remove focus from any edit text
LinearLayout scrollViewLL = (LinearLayout) mainScrollView.getChildAt(0);
scrollViewLL.requestFocus();
break;
}
return false;
}
});
And finally, a way to handle when the user touches outside an edit text to hide the keyboard and put the scroll view back to its original position (found this on web and changed a little to fit my needs):
public void setupUI(View view) {
// Set up touch listener for non-text box views to hide keyboard.
if (!(view instanceof EditText)) {
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// put the scroll view back to its original position
if (v instanceof ScrollView) {
v.setPadding(0, 0, 0, 0);
LinearLayout scrollViewLL = (LinearLayout) ((ScrollView) v).getChildAt(0);
scrollViewLL.requestFocus();
}
hideKeyboard();
return false;
}
});
}
// If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView);
}
}
}
This is a late answer, but it may be helpful for anyone that is still looking for an alternative solution. I created a custom ViewTreeObserver.OnGlobalLayoutListener that may fit your use case if you're looking for a way to control the position of the View that you want to ensure is visible when the soft keyboard is shown. Here is a gist to that solution.
The OnGlobalLayoutListener animates changes to the view's translationY property by smoothly moving the view just above the soft keyboard bounds when the keyboard is shown and back to the view's starting position when the the keyboard is dismissed. Let me know if you have any questions on usage.
Put all of your top code in ScrollView, not just view_1. This allows you to move all the parent layout on click by any child EditText.
EDIT: view_1 in this case MUST NOT contains ScrollView!
If you create the Activity using Android Studio Basic Activity wizard (with CoordinatorLayout and theme="#style/AppTheme.NoActionBar"), the default behavior is adjustPan, where the top portion of the activity is push offscreen and the EditText is shown above the Keyboard. You can also change it to adjustResize where the top portion of the activity is maintained.
Edit AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application ...>
<activity
android:name=".TestInputActivity"
android:label="#string/title_activity_test_input"
android:windowSoftInputMode="adjustResize"
android:theme="#style/AppTheme.NoActionBar">
</activity>
</application>
</manifest>
Keep in mind though the effect and behavior might differ slightly if you are using Scrolling Activity, such as NestedScrollView.
https://code.luasoftware.com/tutorials/android/move-layout-when-keyboard-shown/
android:weightSum="1"
add this
The below code is working for me. Just try this example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/RelativeAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context="com.example.scrollview.MainActivity">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<EditText
android:id="#+id/editTextUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="100dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Name" />
<EditText
android:id="#+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="#+id/editTextUserName"
android:layout_alignLeft="#+id/editTextUserName"
android:layout_alignRight="#+id/editTextUserName"
android:layout_alignStart="#+id/editTextUserName"
android:layout_below="#+id/editTextUserName"
android:layout_marginTop="20dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="Address" />
<Button
android:id="#+id/buttonLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/address"
android:layout_centerHorizontal="true"
android:layout_marginTop="47dp"
android:text="Button" />
</RelativeLayout>
</ScrollView>
</RelativeLayout>
In manifest.xml add these line:
android:theme="#style/AppTheme"
android:windowSoftInputMode="stateHidden|adjustPan"
Declare AppTheme in style.xml as per your theme requirement. Then if you do not need keyboard comes up while page loads, you can add below line in activity:
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Happy Coding :-)
OK, I have a complete layout built; however, I am not really pleased with the long xml file that has resulted. I have a shorted version of the xml outline and designer view below. And I was wondering how I can abstract out each group of similar components into their own custom control.
For example, in the picture below, I have highlighted one such control that I would like to abstract out. Instead of it being a LinearLayout with 2 TextView's inside with their own properties and attributes set. I would like to reference it via <package-name.individual_song_item
android:layout...> ... </>. All I would have to do is set the first TextView's text along with the second one via attributes in the top-level component.
How can this be done? I have the layout done and complete, but I don't like that nothing is abstracted away.
So the expected results that I am looking for are (if you look at the right-side of the image. there would only be one LinearLayout below the image, and the rest would be <package-name.individual_song_item>)
I have tried to just create a new layout xml with just the subsets of components, but I was not able to make it work when combining it back.
OLD WAY
<LinearLayout >
<ImageView />
<LinearLayout >
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
<LinearLayout >
<TextView />
<TextView />
</LinearLayout>
....
</LinearLayout>
</LinearLayout>
POSSIBLE PROPOSED WAY
<LinearLayout >
<ImageView />
<LinearLayout >
<com.example.individual_song_item />
<com.example.individual_song_item />
<com.example.individual_song_item />
....
<com.example.individual_song_item <!-- example (possible!?!?) -->
....
app:label="Group"
app:value="Group Name" />
</LinearLayout>
</LinearLayout>
Create a custom layout eg.
public class IndividualSongItem extends LinearLayout {
private String mSong;
private String mSongName;
public IndividualSongItem(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public IndividualSongItem(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.IndividualSongItem);
try {
// Read in your custom layout's attributes,
// for example song and songName text attributes
CharSequence s = a.getString(R.styleable.IndividualSongItem_song);
if (s != null) {
setSong(s.toString());
}
s = a.getString(R.styleable.IndividualSongItem_songName);
if (s != null) {
setSongName(s.toString());
}
} finally {
a.recycle();
}
}
....etc
You will also need to create an attributes XML for your new layout class.
For a full example of how to do what you're after look at the LabelView example in the ApiDemos.
It's also very well explained here.
What I have:
Right now I have a Scroll view as a parent. Inside this scroll view, I am using a WebView that loads a URL and then shows text in it.
Here is my xml:
<ScrollView
android:id="#+id/parentScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/Heading" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp" >
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#drawable/webview" />
</RelativeLayout>
</ScrollView>
What I want:
I want to scroll webView inside it. When I touch the webView, unfortunately the parent scroll view gets called.
I have to keep Parent scroll view also but besides this I want to scroll WebView content inside it when I touch on webView.
How can I do this?
Create a Custom Touch Intercepting Webview
CustomWebview.java
package com.mypackage.common.custom.android.widgets
public class CustomWebview extends WebView {
public CustomWebview(Context context) {
super(context);
}
public CustomWebview(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomWebview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean onTouchEvent(MotionEvent event){
requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(event);
}
}
in layout.xml
<com.package.custom.widgets.CustomWebview
android:id="#+id/view_extra"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
According to Android design documents you should never put a scrolling container inside a scrolling container if they scroll the same direction. It's not meant to handle such a thing.
I had the same problem. You should set your webView Height equal as its content. for this do this:
add this lines to your onCreate method in Activity:
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:MyApp.resize(document.body.getBoundingClientRect().height)");
super.onPageFinished(view, url);
}
});
webView.addJavascriptInterface(this, "MyApp");
and add this method to your activity:
#JavascriptInterface
public void resize(final float height) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
webView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density)));
}
});
}
Nested scrollable widgets are generally discouraged. It is a confusing user experience because it's easy to scroll the wrong thing. Say I intend to scroll the outer scroll region but I touched the inner region first and flinged really hard. Then the inner one will scroll and I'll be like huh? Why didn't it scroll?
Even if one scrolls horizontal and the other is vertical the gesture recognizers might confuse one for another so you get the same effect. It's a valid use case but it's still iffy and I'd avoid it. (IE: Humans don't perfectly swipe vertically and horizontally properly, it's usually with an angle.)
I would push to change the design to break out the scrollable areas. Ideally 1 scrollable item per page. Even propose one yourself and provide to the designer both experiences and see which one they choose.
To express how this will suck. Look at this example. This isn't a solution but just to show the experience.
<ScrollView
android:id="#+id/parentScroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/Heading" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical"
android:padding="5dp" >
<TextView
android:id="#+id/topText"
android:layout_width="match_parent"
android:layout_height="1000dp"
android:text="#string/lotsoftext" />
<WebView
android:id="#+id/webView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#drawable/webview" />
<TextView
android:id="#+id/topText"
android:layout_width="match_parent"
android:layout_height="1000dp"
android:text="#string/lotsoftext" />
</RelativeLayout>
My activity have a top bar and a bottom bar. the space between topbar and bottom bar i have a linearlayout with several edittext views inside. Because i don't want my layout resize every time the softkeyboard show up, so i set android:windowSoftInputMode="adjustPan" for my activity in manifest. But when the softkeyboard is openned, i want to scroll down to select another edittext to input, it's not allow me do that. Im only able to select the edittext at bottom when i close the softkeyboard. That's very annoying and inconvenient.
How can i get both scrollview and ajustpan mode for softkeyboard work well together?
Please help me out. thanks you so much.
At last, i find out a workaround for my problem, so i want to share for someone maybe get the same problem in future. A brief description of my layout as following:
<myRelativeLayout>
<topbar.../>
<myscrollView>
<linearLayout>
//all stuff controls:editview,textview,....
</linearLayout>
</myscrollView>
<bottombar.../>
i create custom class myRelativeLayout extend RelativeLayout
public class myRelativeLayout extends RelativeLayout{
public interface OnRelativeLayoutChangeListener {
void onLayoutPushUp();
void onLayoutPushDown();
}
private OnRelativeLayoutChangeListener layoutChangeListener;
public myRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);
final int actualHeight = getHeight();
if (actualHeight > proposedheight){
// Keyboard is shown
layoutChangeListener.onLayoutPushUp();
} else if(actualHeight < proposedheight){
// Keyboard is hidden
layoutChangeListener.onLayoutPushDown();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void setLayoutChangeListener(OnRelativeLayoutChangeListener layoutChangeListener) {
this.layoutChangeListener = layoutChangeListener;
}
public OnRelativeLayoutChangeListener getLayoutChangeListener() {
return layoutChangeListener;
}
}
And in my activity , i just set setLayoutChangeListener for myRelativeLayout to hide bottombar when softkeyboard show up and display bottombar when softkeyboard hide:
myRlayout.setLayoutChangeListener(new OnRelativeLayoutChangeListener() {
#Override
public void onLayoutPushUp() {
// TODO Auto-generated method stub
myBottombar.setVisibility(View.GONE);//in my case i need to setVisibility(View.GONE) to bottombar in order for this bar is not displayed when softkeyboard show up.
}
#Override
public void onLayoutPushDown() {
// TODO Auto-generated method stub
myBottombar.setVisibility(View.VISIBLE);// redisplay myBottombar when keyboard is closed.
}
});
Dont forget set android:windowSoftInputMode="adjustResize" for activity.
Hope this useful for someone got the same problem.
put those EditText in a ScrollView like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<EditText
android:id="#+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<requestFocus />
</EditText>
<EditText
android:id="#+id/editText2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/editText3"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>