Reputation: 982
I have extended the Android Sample SoftKeyboard example. What this extension entails is to add two vertical AlphabetLinearLayouts (extended from LinearLayout) above the keyboard, in addition to the LatinKeyBoardView. LatinKeyboardView is a standard keyboard.
When I remove these two side-views from my layout, the behaviour is as expected - selecting inside of an EditText pulls up the soft keyboard, and all the views that were on-screen before get shifted upwards.
Usually when the keyboard pops up in portrait, whatever content was on screen is moved above the keyboard, effectively pushing some content off the screen to make room for the keyboard.
I think that because I have these two extra vertical views as part of my keyboard, the framework tries to push the content up and fails, because the keyboardview takes up too much space.
I'm trying to figure out how to resolve this issue. The best case scenario would be to somehow get my vertical views to display over the original content, with no further displacement other than what's needed to show the soft keyboard.
I construct my KeyboardView as follows:
@Override public View onCreateInputView() {
RelativeLayout outer = (RelativeLayout) getLayoutInflater().inflate(
R.layout.input, null);
// Set up keyboard view.
mInputView = (LatinKeyboardView) outer.findViewById(R.id.keyboard);
mInputView.setOnKeyboardActionListener(this);
mInputView.setKeyboard(mQwertyKeyboard);
// Maintain reference to APC.
mAlphabetViewLeft = (AlphabetColumnLayout)outer.findViewById(R.id.alphabet_list_left);
mAlphabetViewRight = (AlphabetColumnLayout)outer.findViewById(R.id.alphabet_list_right);
// Set of references to handle touches.
mAlphabetViewLeft.setTouchResolver(mTouchResolver);
mAlphabetViewRight.setTouchResolver(mTouchResolver);
return outer;
}
And my input.xml file looks like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res/com.example.android.softkeyboard">
<com.example.android.softkeyboard.AlphabetColumnLayout
android:id="@+id/alphabet_list_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_above="@+id/keyboard"
android:orientation="vertical"
app:available_letters="BGHIJKLMNOPUVY"/>
<com.example.android.softkeyboard.AlphabetColumnLayout
android:id="@+id/alphabet_list_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_above="@+id/keyboard"
android:orientation="vertical"
app:available_letters="ACDEFQRSTWXZ"/>
<com.example.android.softkeyboard.LatinKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
Finally, I set up the AlphabetColumnLayouts using the following code. What this does is it creates a bunch of letters running down each side of the screen above the keyboard (my two input views I mentioned above). AlphabetTextView is a normal TextView with some extra stuff to help me resolve the touches in the way that I want to. char[] letters is instantiated using the app:available_letters style from input.xml.
public void instantiateViews(char[] letters, int appSize) {
Context context = mWeakContext.get();
assertNotNull(context);
// Set up layout params of parent based on the screen size available,
// keeping XML-defined params.
RelativeLayout.LayoutParams lp =
(RelativeLayout.LayoutParams) getLayoutParams();
if (lp == null) {
lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
}
lp.height = appSize/2;
Log.e(TAG, "LinearLayout = " + lp.debug(""));
setLayoutParams(lp);
// Set up the child TextViews.
final int nLetters = letters.length;
for (char c : letters) {
AlphabetTextView tv = new AlphabetTextView(context, this);
LinearLayout.LayoutParams tlp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
lp.height/nLetters);
tv.setLayoutParams(tlp);
//tv.setGravity(Gravity.CENTER);
tv.setText(String.valueOf(c));
tv.setTextSize(12);
tv.setTypeface(Typeface.DEFAULT_BOLD);
// Add child to Layout.
addView(tv);
}
setOnTouchListener(this);
}
Here's a link to the Android Groups question I posted with some attached images.
Upvotes: 1
Views: 2114
Reputation: 3749
Your description isn't very clear. What are you actually seeing that is wrong? Further, what you describe sounds like you want to create your own version of candidates? Does implementing onCreateCandidateViews()
not suit your needs?
Update
Looking at the screenshots, I now understand what you mean.
I think that you're essentially on a road to pain. What you've created is a KeyboardView
that is of the size of that View
, the height of which includes those TextView
columns (unsurprisingly enough). How an app interacts with an input method isn't up to the input method, but up to the app itself. In this case the Messaging app appears to have its android:windowSoftInputMode
set as adjustResize
(hence it 'sitting' on top of your KeyboardView
following an orientation change - I've no idea why it doesn't resize when your input method is first shown).
Further, even if you did manage to get the underlying app to behave, you'll then face the issue of your input method possibly stealing touch events from the app itself (i.e. your KeyboardView
is still a rectangle that sits at the bottom of the screen, no matter what transparency there is in there.
Essentially, Android's IME framework is geared towards the input method being a single root View, which it sticks in a Dialog
, and shows it at the bottom of the screen. It could be that the more recent framework changes have shifted away from this; a new Keyboard
ctor was added which allowed the client to specify width and height, rather than just assuming that the Key
size percentages were of the screen width/height.
Anyway, whilst it may be possible do other stuff it's just that the IME has to do what apps expect, which is the golden rule, since if your IME doesn't interoperate with users' apps, then they won't use it.
Upvotes: 1