I'm developing a custom keyboard and would like to add a TextView above the keyboard to show what the user already has typed or suggestions for words he could want to type.
To do that I have the following layout:
<?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="wrap_content"
>
<android.inputmethodservice.KeyboardView
android:id="#+id/keyboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:keyPreviewLayout="#layout/preview"
android:keyBackground="#drawable/key_background"
android:background="#color/color_primary"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/keyboard"
android:padding="8dp"
android:gravity="center"
android:background="#color/color_primary_dark"
android:textColor="#android:color/white"
android:text="some sample text"
/>
</RelativeLayout>
and the following code at the InputMethodService:
public class FancyInputMethodService extends InputMethodService {
#Override
public View onCreateInputView() {
final RelativeLayout layout = (RelativeLayout) getLayoutInflater().inflate(R.layout.keyboard_layout, null);
final KeyboardView keyboardView = (KeyboardView) layout.findViewById(R.id.keyboard);
final Keyboard keyboard = new Keyboard(this, R.xml.qwerty);
keyboardView.setKeyboard(keyboard);
return layout;
}
}
At a normal EditText at the top of the screen the keyboard looks fine and works well:
But if the EditText is in an Activity which uses the flag android:windowSoftInputMode="adjustResize" in the manifest, the keyboard view seems to cover the actual view instead of being transparent.
The left image shows the actual view with the soft keyboard closed, the image in the middle shows the weird behavior when the keyboard is open and the image on the right shows the default keyboard with the behavior I would expect.
I already tried to set the layouts background to transparent, but that didn't help.
The problem appears at several apps, e.g. WhatsApp, Hangouts, Facebook etc...Am I missing something or what's wrong?
tl;dr
You are not using InputMethodService as intended, use the CandidateView framework instead.
Full answer:
Your keyboard layout should not include the text suggestions.
Override the InputMethodService#onCreateCandidatesView. It should look like this:
public View onCreateCandidatesView() {
mYourView = getLayoutInflater().inflate(R.layout.your_view, null);
return mYourView;
}
3. When you want to show/hide your candidate view use setCandidatesViewShown(boolean show)
Related
I have ConstraintLayout with ScorllView and Button below it (attached to bottom of the screen. When I am editing EditText input inside ScrollView. Then appearing keyboard is moving my ScrollView content up (desired behaviour, so I can scroll to the end of it) but it also pushing button up (undesired behaviour).
I think I can change windowAdjustMode, maybe I could detect keyboard showing and then hide this button? But this two solutions aren't perfect.
XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="#id/submitButton"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="0dp">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText /> goes here
</android.support.constraint.ConstraintLayout>
</ScrollView>
<Button
android:id="#+id/submitButton"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_margin="0dp"
android:text="#string/wizard_singup_step_submit_button"
style="#style/FormSubmitButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
This might help, haven't tried it myself, try adding the below code to your activity tag inside your manifest
Edit - added stateHidden to achieve what you're looking for, the button will be at the bottom and the elements inside the scroll view can be scrolled.
android:windowSoftInputMode="adjustPan|stateHidden"
From Android Documentation -
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.
Edit 2 - Code for calculating the height of the Keyboard
myLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Rect r = new Rect();
parent.getWindowVisibleDisplayFrame(r);
int screenHeight = parent.getRootView().getHeight();
int heightDifference = screenHeight - (r.bottom - r.top);
Log.d("Keyboard Size", "Size: " + heightDifference);
}
});
Add that heightDifference by creating a View Programmatically and setting it's height.
Edit 3 -
Use this to hide the keyboard
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Let me know if this works.
In one of the fragments in my app I have an edittext, and whenever I click on it the keyboard comes up and all the content in the fragment just disappears, including the edittext. I can still type on the keyboard, and after I press the back button, everything comes back and whatever I type is showing on the edittext, but how do I stop everything from disappearing?
Below is the code for the fragment and its layout.
Fragment:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class PaymentsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_payments, container, false);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/editText2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Enter Something"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="#+id/button2"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp" />
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBaseline_toBaselineOf="#+id/editText2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="#+id/editText2"
android:layout_marginLeft="0dp"
android:layout_marginRight="16dp" />
</android.support.constraint.ConstraintLayout>
Reference : Developer documentation
android:windowSoftInputMode
The adjustment made to the activity's main window — whether it is
resized smaller to make room for the soft keyboard or whether its
contents pan to make the current focus visible when part of the window
is covered by the soft keyboard.
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.
Use this way in manifest :
<activity android:windowSoftInputMode="adjustResize"> </activity>
I still reproduce it in the case of a "Multiline EditText in Scrollview in fragment in ConstraintLayout" even on Android 8. Using a SingleLine does not create any issue.
It is happening because the dynamic height of a EditText does not work well in this situation.
This solution was hackish, but it does work like a charm if you can afford to fix the number of lines:
Create a custom class LabelEditView extending EditText
Add an attribute
<declare-styleable name="LabelEditView">
<attr name="label_edit_line_count" format="integer" />
</declare-styleable>
In the constructor call:
setLineCount(attributes.getInt(R.styleable.LabelEditView_label_edit_line_count,
1));
Then, finally, the interesting piece of code:
/**
* Set the number of visible lines. Does not support to switch between modes or font
*/
public void setLineCount(int lineCount) {
if (lineCount <= 1) {
setSingleLine(true);
} else {
setSingleLine(false);
setImeOptions(EditorInfo.IME_ACTION_DONE);
setRawInputType(InputType.TYPE_CLASS_TEXT);
// Fix around EditText in Scrollview in fragment in ConstraintLayout
Paint.FontMetrics fm = getPaint().getFontMetrics();
int textHeight = (int) ((fm.bottom - fm.top) * (lineCount + 0.5));
setMaxHeight(textHeight);
setHeight(textHeight);
}
}
Put in AndroidManifest.xml (in your activity):
<activity android:name="(activity name)" android:windowSoftInputMode="adjustPan">
I have a grid view and want to show a keyboard when the user clicks on a cell. The input of the keyboard will then appear in the cell. I've tried the code below which I got from Android: show soft keyboard automatically when focus is on an EditText and other similar questions. I can't get the keyboard to show up, though.
Any ideas on this?
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,int position, long id) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(gridView, InputMethodManager.SHOW_IMPLICIT);
}
});
I have tried InputMethodManager.SHOW_FORCED but that didn't help either.
Thanks
EDIT
The cell layout for the grid is below. I changed it to an EditText but still no keyboard. Having it as EditText doesn't look too good for me from a UI point of view. Ideally, I was the TextView and then perhaps when the user clicks it becomes an EditText so the user can enter something.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp" >
<EditText
android:id="#+id/grid_item_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#+id/celllabel"
android:textSize="15px" >
</EditText>
My idea is that it stays as a TextView. The keyboard opens and when the user clicks one letter the keyboard closes and that a letter appears in the GridCell. Is my idea possible?
Thanks
One suggestion:
Create a custom EditText, you can hide the cursor if you want (make it looks like a TextView).
Optimize your cell layout by removing the LinearLayout
Code:
<?xml version="1.0" encoding="utf-8"?>
<YourCustomEditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_item_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#+id/celllabel"
android:maxLength="1"
android:textSize="15px" >
</YourCustomEditText>
Use TextWatcher or focus interface to control the show/hide of the keyboard.
Hope this help!
Thata code insted
keyboardview or one of its extended class. You have not shared your RelativeLayout but i think The exception may be because of some problem with your RelativeLayout.
You can put a button to the right of Keyboard like this(res/layout/input.xml):
< com.android.example.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/keyboard"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_height="wrap_content"
android:keyBackground="#drawable/kb_exagon_base"
You can use any View/ViewGroup as a keyboard layout, Infact you can even set the keyboard layout to a view which is not an instance of keyboardview or one of its extended class. You have not shared your RelativeLayout but i think The exception may be because of some problem with your RelativeLayout.
You can put a button to the right of Keyboard like this(res/layout/input.xml):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/keyboardLayout"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
>
<android.inputmethodservice.KeyboardView
android:id="#+id/keyboardView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#drawable/ic_launcher"/>
And then return an instance of this layout from OnCreateInputView.
Update:
The statement mInputView = (KeyboardView) getLayoutInflater().inflate( R.layout.input, null); in your below comment will throw ClassCastException as the inflated view is not an instance of KeyboardView.
you need to change it like this:
public View onCreateInputView() {
mInputView = (View)getLayoutInflater().inflate( R.layout.input, null);
mKeyboardView = (KeyboardView)mInputView.findViewById(R.id.keyboardView);
mKeyboardView.setOnKeyboardActionListener(this);
mKeyboardView.setKeyboard(mQwertyKeyboard);
return mInputView;
}
the keyboard pops up from the bottom and you can define the behavior in your manifest using the following line android:windowSoftInputMode:
<activity
android:name=".NAME"
android:label="#string/appName"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="#style/Theme.HOLOorAnyThemeYouWant"
android:windowSoftInputMode="stateAlwaysHidden" >
from documentation :
android:windowSoftInputMode
How the main window of the activity interacts with the window containing the on-screen soft keyboard. The setting for this attribute affects two things:
The state of the soft keyboard — whether it is hidden or visible — when the activity becomes the focus of user attention.
The adjustment made to the activity's main window — whether it is resized smaller to make room for the soft keyboard or whether its contents pan to make the current focus visible when part of the window is covered by the soft keyboard.
What is the simplest way to attach a layout defined in xml at the top of Android soft keyboard.
This view should only appear when the keyboard appears.
I think the best way is to detect when the keyboard appears and then attach view to the bottom of the screen (it will be above the keyboard after resizing all layout).
I think the cleaner way to do this.
Define a layout resource file to use as your custom view
Create a method which inflates this layout resource file and return it as a view:
Code Snippet
public View returnPayKeyView(){
View simpleView = getLayoutInflater().inflate(R.layout.simpleresource,null);
return simpleView;
}
Set this returned view as the candidates using the setCandidatesView Method
The returned view will show above your keyboard, using the inflated xml layout resource.
One approach is to wrap your usual view layout in a FrameLayout and put the bit you want above the keyboard inside the frame along with your other view layout with a layout gravity of bottom.
My layout was along these lines:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- all your stuff... -->
</LinearLayout>
</ScrollView>
<LinearLayout
android:id="#+id/stuffAboveKeyboardLayout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="bottom"
android:orientation="horizontal"
android:background="#DDD">
<!-- stuff above keyboard... -->
</LinearLayout>
</FrameLayout>
The downside is that it will show even when the keyboard is hidden - but it ought to be possible to show / hide the view when the keyboard shows / hides: How do I Detect if Software Keyboard is Visible on Android Device?