为 Android 键盘动态应用主题
Apply theme dynamically for Android Keyboard
大家好,Whosebug 的各位,
我在编程软键盘时遇到问题:
我想要实现的是软键盘动态加载一个针对夜间打字优化的 theme/style 和一个针对阳光下打字的 theme/style。样式已经定义,我已经可以通过仅更改 input.xml.
中的样式轻松切换它们
import ... /*Not quite relevant (yet)*/
public class LatinKeyboardView extends KeyboardView {
public LatinKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, loadColor());
}
public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public static int loadColor() {
String dbg = android.os.Debug.isDebuggerConnected() ? "Y" : "N";
android.util.Log.d("loadColor", "Debugger connected: " + dbg);
android.os.Debug.waitForDebugger();
int temp = 0;
int id = 0;
if (temp == 1)
{
id = R.style.KeyStyle_Day;
}
else
{
id = R.style.KeyStyle_Night;
}
android.util.Log.d("loadColor", Integer.toString(id));
return id;
}
当我将调用从第一个构造函数重定向到第二个构造函数时(如 Hacker's Keyboard 源代码所示),软键盘成功加载了 loadColor() 中的样式 id,但之后,内部发生异常我无法追溯,即使有堆栈跟踪:
03-19 08:32:48.313 18630-18630/com.alphanerd.eztype.keyboard E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.alphanerd.eztype.keyboard, PID: 18630
android.view.InflateException: Binary XML file line #21: Error inflating class com.alphanerd.eztype.keyboard.LatinKeyboardView
at android.view.LayoutInflater.createView(LayoutInflater.java:626)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at android.view.LayoutInflater.createView(LayoutInflater.java:600)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.inputmethodservice.KeyboardView.<init>(KeyboardView.java:370)
at com.alphanerd.eztype.keyboard.LatinKeyboardView.<init>(LatinKeyboardView.java:53)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at android.view.LayoutInflater.createView(LayoutInflater.java:600)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
我希望,你能帮助我。动态加载颜色的代码目前和int temp一样动态; ,但稍后我将实现从 sharedpreferences 加载颜色的逻辑(键盘实际上是为了(光学地)与我公司正在开发的另一个应用程序集成)
在此先感谢您的帮助:)
我找到了一个解决方案,我一找到它就认为它非常简单:我没有修改任何构造函数等,而是编辑了被覆盖的 onCreateInputView :
@Override
public View onCreateInputView() {
int schema = loadColor();
//Default code
//mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
// R.layout.input, null);
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
schema, null);
mInputView.setOnKeyboardActionListener(this);
mInputView.setKeyboard(mQwertyKeyboard);
return mInputView;
}
public static int loadColor() {
String dbg = android.os.Debug.isDebuggerConnected() ? "Y" : "N";
android.util.Log.d("loadColor", "Debugger attached: " + dbg);
//android.os.Debug.waitForDebugger(); //Comment this out before releasing the keyboard
int temp = 1;
int id = 0;
if (temp == 1)
{
id = R.layout.input_day;
}
else
{
id = R.layout.input;
}
android.util.Log.d("loadColor", Integer.toString(id));
return id;
}
通常情况下,LayoutInflater 会加载 google 预期的默认输入布局。我可以推荐定义多个输入布局,每个布局都有自己的风格。如果您自己的自定义键盘应支持用户制作的主题,只需创建一个输入布局并在其中引用一种样式,即引用主题图像。将所有已加载的已加载主题图像放在主题化输入 xml.
可访问的特殊文件夹中
最后一个提示:您可以通过放置 android.os.Debug.waitForDebugger(); 来调试软键盘;在代码中。键盘(或任何其他应用程序)将等待调试器连接。请记住在发布您的应用程序之前删除每个 waitForDebugger() 调用,否则应用程序将在您忘记删除此行的任何地方停止 运行。我希望,我可以帮助任何阅读本文的人。
谢谢你,祝你有愉快的一天:)
大家好,Whosebug 的各位,
我在编程软键盘时遇到问题:
我想要实现的是软键盘动态加载一个针对夜间打字优化的 theme/style 和一个针对阳光下打字的 theme/style。样式已经定义,我已经可以通过仅更改 input.xml.
中的样式轻松切换它们import ... /*Not quite relevant (yet)*/
public class LatinKeyboardView extends KeyboardView {
public LatinKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, loadColor());
}
public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public static int loadColor() {
String dbg = android.os.Debug.isDebuggerConnected() ? "Y" : "N";
android.util.Log.d("loadColor", "Debugger connected: " + dbg);
android.os.Debug.waitForDebugger();
int temp = 0;
int id = 0;
if (temp == 1)
{
id = R.style.KeyStyle_Day;
}
else
{
id = R.style.KeyStyle_Night;
}
android.util.Log.d("loadColor", Integer.toString(id));
return id;
}
当我将调用从第一个构造函数重定向到第二个构造函数时(如 Hacker's Keyboard 源代码所示),软键盘成功加载了 loadColor() 中的样式 id,但之后,内部发生异常我无法追溯,即使有堆栈跟踪:
03-19 08:32:48.313 18630-18630/com.alphanerd.eztype.keyboard E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.alphanerd.eztype.keyboard, PID: 18630
android.view.InflateException: Binary XML file line #21: Error inflating class com.alphanerd.eztype.keyboard.LatinKeyboardView
at android.view.LayoutInflater.createView(LayoutInflater.java:626)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at android.view.LayoutInflater.createView(LayoutInflater.java:600)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.inputmethodservice.KeyboardView.<init>(KeyboardView.java:370)
at com.alphanerd.eztype.keyboard.LatinKeyboardView.<init>(LatinKeyboardView.java:53)
at java.lang.reflect.Constructor.constructNative(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at android.view.LayoutInflater.createView(LayoutInflater.java:600)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
at android.view.LayoutInflater.inflate(LayoutInflater.java:470)
at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
at com.alphanerd.eztype.keyboard.EZTypeKeyboard.onCreateInputView(EZTypeKeyboard.java:125)
at android.inputmethodservice.InputMethodService.updateInputViewShown(InputMethodService.java:1594)
at android.inputmethodservice.InputMethodService.showWindowInner(InputMethodService.java:2220)
at android.inputmethodservice.InputMethodService.showWindow(InputMethodService.java:2179)
at android.inputmethodservice.InputMethodService$InputMethodImpl.showSoftInput(InputMethodService.java:712)
at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMethodWrapper.java:214)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:40)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5335)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
我希望,你能帮助我。动态加载颜色的代码目前和int temp一样动态; ,但稍后我将实现从 sharedpreferences 加载颜色的逻辑(键盘实际上是为了(光学地)与我公司正在开发的另一个应用程序集成)
在此先感谢您的帮助:)
我找到了一个解决方案,我一找到它就认为它非常简单:我没有修改任何构造函数等,而是编辑了被覆盖的 onCreateInputView :
@Override
public View onCreateInputView() {
int schema = loadColor();
//Default code
//mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
// R.layout.input, null);
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
schema, null);
mInputView.setOnKeyboardActionListener(this);
mInputView.setKeyboard(mQwertyKeyboard);
return mInputView;
}
public static int loadColor() {
String dbg = android.os.Debug.isDebuggerConnected() ? "Y" : "N";
android.util.Log.d("loadColor", "Debugger attached: " + dbg);
//android.os.Debug.waitForDebugger(); //Comment this out before releasing the keyboard
int temp = 1;
int id = 0;
if (temp == 1)
{
id = R.layout.input_day;
}
else
{
id = R.layout.input;
}
android.util.Log.d("loadColor", Integer.toString(id));
return id;
}
通常情况下,LayoutInflater 会加载 google 预期的默认输入布局。我可以推荐定义多个输入布局,每个布局都有自己的风格。如果您自己的自定义键盘应支持用户制作的主题,只需创建一个输入布局并在其中引用一种样式,即引用主题图像。将所有已加载的已加载主题图像放在主题化输入 xml.
可访问的特殊文件夹中最后一个提示:您可以通过放置 android.os.Debug.waitForDebugger(); 来调试软键盘;在代码中。键盘(或任何其他应用程序)将等待调试器连接。请记住在发布您的应用程序之前删除每个 waitForDebugger() 调用,否则应用程序将在您忘记删除此行的任何地方停止 运行。我希望,我可以帮助任何阅读本文的人。
谢谢你,祝你有愉快的一天:)