I'm building an android soft keyboard and I can't seem to fix this bug - I have an Arabic and QWERTY keyboard and when I rotate my device on the QWERTY keyboard (or even Arabic shift), it's as if my program has "restarted" and it becomes the Arabic Keyboard without shift.
The onSaveInstanceState(Bundle savedInstanceState) does not work because my application does not extend Activity but InputMethodService.
I put the following in my android manifest
android:configChanges="keyboard|keyboardHidden|orientation"
android:windowSoftInputMode="stateUnchanged|adjustResize">
I tried using
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(MYDEBUG, "Config Changed " + currentKeyboard.equals(qwerty));
}
However, currentKeyboard.equals(qwerty)) always results to false and I made sure it was true just before the orientation change.
Any help would be much appreciated.
I think its the applications fault. If the application is restarting on orientation changes, then your input connection is being torn down and rebuilt to a new edit text. This means the keyboard would see it as a new connection and will start in the default state. To test this, write a test app that turns off restarts on configuration change and see if it still happens to keyboards in that app.
Alright, after mind boggling thinking I realized the issue was with the line of code super.onConfigurationChanged(newConfig);
When removed, my code would change orientation but my keyboard would not be resized. Since I love the re-sizing feature of the parent, I made an array that contains all the keyboards and after changing orientation, I would update the array so that the keyboard array would have the right sizes.
#Override
public void onConfigurationChanged(Configuration newConfig) {
int currentKeyboard = 0;
boolean isShifted = kv.isShifted();
for (int i = 0; i < keyboard.length; i++) {
if(kv.getKeyboard().equals(keyboard[i])){
currentKeyboard = i;
break;
}
}
super.onConfigurationChanged(newConfig);
initializeKeyboardArray();
setKeyboard(keyboard[currentKeyboard]);
kv.setShifted(isShifted);
}
private void initializeKeyboardArray(){
keyboard = new Keyboard[7];
keyboard[ARABIC] = arabic;
keyboard[ARABIC_SHIFT] = arabicShift;
keyboard[ARABIC_SYMBOLS] = arabicSymbols;
keyboard[ARABIC_SYMBOLS_SHIFT] = arabicSymbolsShift;
keyboard[QWERTY] = qwerty;
keyboard[QWERTY_SYMBOLS] = qwertySymbols;
keyboard[QWERTY_SYMBOLS_SHIFT] = qwertySymbolsShift;
}
Not sure if this is a roundabout way of solving the problem or if this is the right way so if anyone knows a better way - please let me know.
Related
I have a spinner that has numbers from 1 - 10. If the user selects anything above 1, a certain EditText that is INVISBLE becomes VISIBLE, this is what I want. But when I change it from portrait to landscape, it goes back to INVISIBLE.
This is where the changing happens
btn_Calc.setOnClickListener(new View.OnClickListener() {
#Override
if (split > 1) {
et_APP.setVisibility(View.VISIBLE);
tv_app.setVisibility(View.VISIBLE);
vis = 1;
}
else{
et_APP.setVisibility(View.INVISIBLE);
tv_app.setVisibility(View.INVISIBLE);
vis = 2;
}
});
And I tried to do onSaveInstanceState like this
if(savedInstanceState != null) {
int isVis = savedInstanceState.getInt("vis", 2);
if(isVis == 1){
et_APP.setVisibility(View.VISIBLE);
tv_app.setVisibility(View.VISIBLE);
}
else{
et_APP.setVisibility(View.INVISIBLE);
tv_app.setVisibility(View.INVISIBLE);
}
}
public void onSaveInstanceState(Bundle savedInstanceState){
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("getVisible", vis);
}
Sorry for poor formatting, I cut out unrelated code.
It works that if the selected item in the spinner is greater than 1 and I click the calc button, it shows the fields I want but when I change orientation they dissapear again. Any ideas on how I can get to stay visible when I change the orientation?
The names of your keys don't match between save and load.
Saving:
savedInstanceState.putInt("getVisible", vis);
Restoring:
int isVis = savedInstanceState.getInt("vis", 2);
The layout is being recreated if you don't want Android to do anything add the following line:`android:configChanges="keyboardHidden|orientation|screenSize"' to the activity in the manifest.
I'm developing an IME for Android, which includes some highlighting of the text input by the user with a background colour (using SpannableString).
When the device is rotated and the keyboard is redrawn, the text remains in the input box as entered by the user, however, all styling (i.e. background colour) is lost.
Any ideas why this might be happening and how to circumvent it?
I have found a solution, which is not perfect, but it works.
Set up an ExtractedText variable in the IME service class.
In the OnConfigurationChanged method, get the extracted text. Then in the onStartInputView method, delete the text in the bound editor, and replace it with the extracted text.
#Override
public void onConfigurationChanged (Configuration newConfig)
{
//get what's been input so far
ExtractedTextRequest req = new ExtractedTextRequest();
req.token = 0;
req.flags = InputConnection.GET_TEXT_WITH_STYLES;
extractedText = ic.getExtractedText(req, 0);
super.onConfigurationChanged(newConfig);
}
#Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
...
if(extractedText!=null)
{
if(ic.deleteSurroundingText(9999, 0))
{
ic.commitText(extractedText.text, 1);
Log.i("onStartInputView", "Text Replaced");
}
else
{
Log.i("onStartInputView", "IC not valid");
}
}
super.onStartInputView(attribute, restarting);
}
Problem is shown in picture , please go light on me , i'm not that experienced in android
but trying my best to do so...
Tried this in my Main.java:
package com.faisal.my_calculator;
import android.content.SharedPreferences;
// all remaining imports here.
public class Main extends ActionBarActivity implements View.OnClickListener {
// Buttons
Button btnOne, btnTwo, btnThree, btnFour, btnFive, btnSix, btnSeven,..., btnTan, btnExit;
case R.id.three:
if (y != 0) {
y = 0;
etDisp.setText("");
}
str = str.append(btnThree.getText());
etDisp.setText(str);
break;
.
.
.
.
case R.id.add:
if (TextUtils.isEmpty(etDisp.getText().toString())) {
return;
}
operator = "+";
if (x == 0) {
x = Double.parseDouble(etDisp.getText().toString());
etDisp.setText("");
} else if (y != 0) {
y = 0;
etDisp.setText("");
} else {
y = Double.parseDouble(etDisp.getText().toString());
etDisp.setText("");
x = x + y;
etDisp.setText(Double.toString(x));
}
break;
I tried for:
appconfigchanges solution = it is not even in my AndroidManifest.xml,
Now to the layout part : In emulator all things are fully spaced on screen but when i run app below(2nd screen comes as a result not like on Emulator which i worked hard and adjusted its full screen) more when i run it on my LG_OG in landscape only starting three rows come on the screen o.O ....? need help here as well ...!
If anything needed more i will post it....!(now almost all code i have posted) Again, be patient to your brother :)
Please don't handle any exception if it is not realy needed to handle. Remove your try catch while initializing the UI and setting clicklistener to buttons and check where your code is failing.
Second you don't need to handle UI changes on orientation change as it will be handled by android itself. This will be done like -on orientation change your activity will be recreated and your oncreate will be again called so set layout and initialize all the UI element in oncrete itself and remove unnecessary code from onConfigurationChanged method.
Always check for the null value in suspected code
if(btnDiv == null)
{
//condition
}
Add following code just before try
if(btnDiv == null)
{
throw new NullPointerException("Button are not initialized");
}
if exception is thrown then your buttons are not initialized.
Yes , what a pain it was , as debugger is the best friend of programmer , i debugged it and it directly took me to the buttons which i didn't make in Landscape but were present in portrait so Eclipse doesn't like this and was causing my different buttons to stay idle but after putting those buttons in landscape xml now everything works all awesome...!
Now just layout make-up is remained as two buttons are running here and there when i run it.! :p
Thanks guys for your time...!
Here's my MAIN ACTIVITY
public static boolean popupStatus=false;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null){
popupStatus = savedInstanceState.getBoolean("Open");
}
setContentView(R.layout.main);
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("Open", DateTimePicker.openPopup);
super.onSaveInstanceState(savedInstanceState);
}
I have DateTimePicker.java class which has 1 button and 1 Textview. Clicking on button, my another class Calendar.java get populated in PopupWindow and this Popup window displays my class Calendar.java . I have created different layouts of my Calendar.java class for portrait and landscape mode. Here's DateTimePicker.java some snippet of code,
public static boolean openPopup = false;
textView = new TextView(this.getContext());
this.addView(textView, layoutParams);
button = new Button(this.getContext());
button.setText("C");
this.addView(button, layoutParams1);
button.setOnClickListener(this);
if(Main.popupStatus){
button.performClick();
}
public void onClick(View v) {
if(Main.popupStatus){
new Handler().postDelayed(new Runnable() {
public void run() {
openCalendar();
}
}, 100);
}
else{
openCalendar();
}
private void openCalendar() {
Calendar calendar = new Calendar(this.getContext());
if(portrait.equals(orientation)){
pw = new PopupWindow(calendarLayout, 245, 284, true);
}
else{
pw = new PopupWindow(calendarLayout, 295, 240, true);
}
pw.setOutsideTouchable(false);
pw.showAtLocation(this, Gravity.NO_GRAVITY, 10, 80);
openPopup = true;
}
public void closeCalendar(){
pw.dismiss();
openPopup = false;
}
Main.XML contain DateTimePicker .
Actually I wanted my Popup window to be opened up even when orientation gets changed at run time, so I have done it through setting flag openPopup = true; in openCalendar() method and if it is opened and orientation gets changed at run time, this flag will be saved in onSaveInstanceState() method. After orientation will change, it will be checked in onCreate() and popup will be opened up for respective orientation mode. I hope you got my point.
PROBLEM: Initially When I click on button in Portrait mode, popup window pops up for portrait layout. then without dismissing popup window, I change the orientation to landscape. And after changing, I can see my popup window as intact and appears on screen of landscape layout. Till now it works fine. But IF popup window is opened up in landscape mode and then I change the orientation to portrait, popup window of portrait layout didn't come up and I see FORCE CLOSE message:/ Please help since I am working behind it so long and getting no clue. I would be very grateful to you all. Thanks!
P.S.: Changing orientation means I am pressing ctrl+F11 and changing orientation of Emulator
The emulator has an odd feature (some consider it a bug) in which changing from landscape to portrait in the emulator causes two configuration changes and two restarts of your activity. (One configuration change is the orientation and the other is an emulated change in the keyboard state.) The timing of the configuration changes frequently causes crashes like this. Try adding this attribute:
android:configChanges="keyboard|keyboardHidden"
to your <activity> tag in the manifest. See if that improves the situation.
Make sure you have your layout defined in layout-land folder and ensure onCreate is not called again and again. android:configChanges="keyboard|keyboardHidden" Put this in your manifest file so that the state is retained when you change orientation
I have a longClick method on a grid view that does not work for the the 0 index position of the underlying ArrayList. However, if I add only one 'SentenceButton' I can remove it but not if I add many 'SentenceButton's.
The primary code is as follows in the SentenceButton class:
public boolean onLongClick(View view) {
boolean result = false;
SentenceButton btnSentence = (SentenceButton)view;
ArrayList<SentenceButton> temp = Utility.getSentenceArray();
if(temp.contains((SentenceButton)view));
result = Utility.getSentenceArray().remove(btnSentence);
Utility.getSentenceArray().trimToSize();
SBActivity.getmSentenceAdapter().notifyDataSetChanged();
return result;
}
This part of the code is made to simply remove an errant entry.
This does not seem to work, ie. remove, the first element of Utility.getSentenceArray and only works intermittently on the other 'SentenceButtons'.
Strangely, the play sound and adding to the Sentence view from the fragment I am using as a content view only seems to work twice in a row and then seems to hang until I rotate the device. The relevant code follows in the SoundButton class:
public void onClick(View view) {
// To Do: add to current sentence
SoundThread sndThread = new SoundThread();
sndThread.start();
Utility.getSentenceArray().add(new SentenceButton(mContext, (SoundButton)view));
SBActivity.getmSentenceAdapter().notifyDataSetChanged();
}
This adds the content view 'SoundButton' as a 'SentenceButton' in the SentenceButton array. Even more strangely to me, if I rotate the device enough it seems to add the 'SoundButton' as a 'SentenceButton'. It even plays the 'SoundButton' as the rotation happens but not before. It as if the onClick of the SoundButton is queued somewhere.
The rotation code is as follows:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE)
{
setFragment(getmFrag());
mSentenceGridView.invalidate();
}
else if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_PORTRAIT)
{
setFragment(getmFrag());
mSentenceGridView.invalidate();
}
super.onConfigurationChanged(newConfig);
}
Could someone help me with this. Definitely a noob here and of course will add any relevant info asked of me.
I am trying to write a soundboard to help my friend's relative communicate better.
Many thanks in advance and especially to a tutorial on a working soundboard.
I am writing this with a Kindle Fire as my testing device.
I discovered part of the problem was not having a proper id for the buttons I am creating