I am trying to create my own keyboard. Using Android Keyboard is not enough for my task so I decided to create inheritor class directly from View.class. As base I decided to use code of Keyboard.class and then start change things one by one.
I faced many problems trying even compile that class, used some reflection and hacks to obtain private fields. I created file attrs to be able to use Keyboard's attributes and tags. Finally class compilled and know it crashes becouse parameteres, that should go from inflating, are null.
What I found out is that method context.obtainStyledAttributes(attrs, R.styleable.MyKeyboardView); returns wrong result and a.getIndexCount(); after that returns 0.
here is my attr.xml file:
<resources>
<declare-styleable name="MyKeyboardView">
<attr name="keyBackground" format="reference" />
<attr name="keyTextSize" format="dimension" />
<attr name="labelTextSize" format="dimension" />
<attr name="state_long_pressable" format="boolean" />
<attr name="keyTextColor" format="color" />
<attr name="keyPreviewLayout" format="reference" />
<attr name="keyPreviewOffset" format="dimension" />
<attr name="keyPreviewHeight" format="dimension" />
<attr name="verticalCorrection" format="dimension" />
<attr name="shadowColor" format="color" />
<attr name="shadowRadius" format="float" />
<attr name="backgroundDimAmount" format="float" />
<attr name="popupLayout" format="reference" />
</declare-styleable>
here is part of my keyboard class:
public MyKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, Resources.getSystem().getIdentifier("keyboardViewStyle", "attr", "android"));
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyKeyboardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.MyKeyboardView);
LayoutInflater inflate =
(LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
int previewLayout = 0;
int keyTextSize = 0;
int n = a.getIndexCount();
This is how I use keyboard in layout:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_gravity="bottom">
<com.test.features.keyboard.MyKeyboardView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyboard_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="2.5dip"
android:keyPreviewHeight="@dimen/key_height"
android:shadowRadius="0"
android:keyPreviewLayout="@layout/keyboard_key_preview"
android:keyPreviewOffset="0dp"
android:keyBackground="@drawable/keyboard_key_background"
android:keyTextColor="@color/keyboard_key_color"
android:background="@color/primary"
android:popupLayout="@layout/keyboard_popup_layout"/>
tried to use it like so, length() returned 11, but switch case found almost no matches. And if found, default value was used:
int n = a.length();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.MyKeyboardView_keyBackground:
mKeyBackground = a.getDrawable(attr);
break;
case R.styleable.MyKeyboardView_verticalCorrection:
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewLayout:
previewLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewOffset:
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
break;
case R.styleable.MyKeyboardView_keyPreviewHeight:
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
break;
case R.styleable.MyKeyboardView_keyTextSize:
mKeyTextSize = a.getDimensionPixelSize(attr, 18);
break;
case R.styleable.MyKeyboardView_keyTextColor:
mKeyTextColor = a.getColor(attr, 0xFF000000);
break;
case R.styleable.MyKeyboardView_labelTextSize:
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
break;
case R.styleable.MyKeyboardView_popupLayout:
mPopupLayout = a.getResourceId(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowColor:
mShadowColor = a.getColor(attr, 0);
break;
case R.styleable.MyKeyboardView_shadowRadius:
mShadowRadius = a.getFloat(attr, 0f);
break;
}
}
Your custom
View
attributes are going to be in your app's namespace, not the system namespace, so they weren't found in the givenAttributeSet
when they had the system namespace prefix on them.Add the
xmlns:app="http://schemas.android.com/apk/res-auto"
namespace declaration either directly in the<MyKeyboardView>
tag, or in an ancestor tag, and change the prefix on all of your attributes toapp
.Note that the prefix can be any valid name you like, though
app
is probably the most common.