I want to make my application compatible with Android Nougat and specifically with the density change and the font size change.
What I am doing in my tests is:
Launch the application
Put it in Multi-Window mode (top part of a Pixel C, portrait mode, on emulator)
Put some filters on a list in my application
Change the display size or the font size through the second half of my screen with the settings app
If I don't listen for configuration changes with the density value in the manifest, it recreates my activity (which is not good because I have some filters on and I lose them).
If I listen to them, the densityDpi value is the same in the newConfig value passed as a parameter than the one I get with getResources().getConfiguration().densityDpi.
My current line on the manifest is as below :
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden|density"
I have tried something like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// some code
if(mOldConfiguration != null && newConfig.densityDpi!= mOldConfiguration.densityDpi){
// Neither densityDpi nor fontScale works, they are always the same
}
if(mOldConfiguration != null && newConfig.fontScale != mOldConfiguration.fontScale){
// I will later have a method which will recreate the activity with my filters saved
recreate();
}
mOldConfiguration = newConfig;
}
I already listen to other configuration changes but can't figure out how to detect in this method that the change was a density / font size change.
You can listen to density changes by add this line in the Manifest file:
android:configChanges="density"
In the activity, you can get the new configuration value when having a change:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e("TRUNGDH", newConfig.densityDpi + "<= densityDpi");
}
With font size changes, you can add some code like this:
android:configChanges="fontScale"
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e("TRUNGDH", newConfig.fontScale + "<= fontScale");
}
Related
In the settings in my phone can I change the font size of apps globally .
Settings> Display> Font size
Can I make the font size (small, normal, large , very large ) also read with Java and, if applicable . set only for my app ?
I tried to change the font size as follows.
Button buttonbig = (Button) dialog.findViewById(R.id.btn_big);
buttonbig.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
float fScale = getResources().getConfiguration().fontScale;
String fontSize = String.valueOf(fScale);
conf.fontScale =fScale + 0.15f;
getResources().getConfiguration().setTo(conf);
TextView textView = (TextView) dialog.findViewById(R.id.lbl_size_act);
textView.setText(fontSize);
}
});
dialog.show();
My Text View shows me the new size . However, the text remains the same size .Have anyone an idea what's wrong ?
First of all, I strongly advise against overriding the language, font size, or other settings, because as you pointed out, this is something you should do globally.
If you want to set it for your whole app, the right place to do so would be in the Application.
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
Configuration configuration = getResources().getConfiguration();
configuration.fontScale *= 2;
getResources().updateConfiguration(configuration, getResources().getDisplayMetrics());
}
}
If you want to change it during runtime, you would also set it in application, but you would have to finish and start your activity again to take effect.
If you want to change only this textView's font size, how about trying
textView.setTextSize(float);
http://developer.android.com/reference/android/widget/TextView.html#setTextSize(float)
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.
I have a simple activity with a boolean. I want it to change from portrait to landscape if and only if that boolean is false (only if the screen changes orientation, of course).
I tried this:
#Override
public void onConfigurationChanged(final Configuration newConfig) {
super.onConfigurationChanged((listening) ? getListeningConfiguration(newConfig)
: newConfig);
setContentView(R.layout.medidor);
preconfigureLayout();
}
public Configuration getListeningConfiguration(final Configuration c) {
c.orientation = Configuration.ORIENTATION_PORTRAIT;
return c;
}
But it simply won't work.
How can I force an activity to remain in portrait state unless I tell it it can change?
In manifest file in activity tag add
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
That will keep your activity in portrait mode. then use your code for orientation change.
Just call this to keep it in portrait:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
That should do the trick
I have code to set a different layout for portrait and landscape. Is there a way to change the layout while the activity is running, if the user flips the device?
Code to set layout
void SetView()
{
int w=getWindowManager().getDefaultDisplay().getWidth();
int h=getWindowManager().getDefaultDisplay().getHeight();
if (w>h)
setContentView(R.layout.mainHor);
else
setContentView(R.layout.mainVer);
}
Make two new folders in res called layout-land and layout-port. Put your landscape layout in layout-land and your portrait in layout-port. Make sure the xml files have the same name.
Also, as was mentioned in the comments, making just the layout-land folder is good enough as long as you also have a default xml for the Activity in the layout folder. If for any reason Android can't find the layout needed in the alternative layout-[orientation] folder, it will take what it finds in layout.
make two folder under res folder with name layout and layout-land. Put seprate layouts for portrait and landscape.
and then override onConfigurationChanged
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.homepage_screen);
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.mainHor);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.mainVer);
}
}
Do this
#Override
public void onConfigurationChanged(Configuration configuration) {
super.onConfigurationChanged(configuration);
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.landscape_layout);
} else if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.portrait_layout);
}
}
I have create dialog box which will be displayed first when i start application (which is coded in onCreate method ) and then question and answer will be displayed on textview
so to solve problem of orientation (so dialog box again not displayed when orientation change) i have used Manifest with:
android:configChanges="keyboardHidden|orientation"
I have res/layout-land, res/layout-port
but to change only COLOR of background
I have used onConfigurationChanged in my Activity (it get's called on rotation).
so now when orientation change the dialog box will not appear again and background is redrawn but the question and answer which is initialized on onCreate() will not display
so how to maintain
Using android:configChanges="keyboardHidden|orientation" means that your activity handles a configuration change itself, and the system will not change the layout.. take a lokk at http://developer.android.com/guide/topics/resources/runtime-changes.html
To reset the text view, in case of not using android:configChanges="keyboardHidden|orientation":
#Override
public Object onRetainNonConfigurationInstance() {
final MyDataObject data = collectMyLoadedData();
//here get the text from the text view, and any other info
return data;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data != null) {
//get the text and set it in the text view
}
}
When you change the orientation of the devide, android continue the execution without calling onCreate again, but if you put the code in onResume, this code will executed again.
In OnCreate add for your main layout as
LinearLayout lv=(LinearLayout)findViewById(R.id.mainlayout);
lv.setBackgroundColor(android.R.color.black); // for default potrait or landscape view and after that add this in that activity
#Override
public void onConfigurationChanged(Configuration newConfig) {
Configuration c = getResources().getConfiguration();
if(c.orientation == Configuration.ORIENTATION_PORTRAIT ) {
// portrait
lv.setBackgroundColor(android.R.color.black);
} else if(c.orientation == Configuration.ORIENTATION_LANDSCAPE ){
// landscape
lv.setBackgroundColor(android.R.color.white);
}
}
and also add this in menifest in your activity defined
android:configChanges="keyboardHidden|orientation"
Did you use onSaveInstanceState to save the data and onRestoreInstanceState for retriving the data?
If you have done this then you can display the same dialog box in onRestoreInstanceState.
Well I have a question for you. How did you kept the background color unchanged when changing the orientations? And what to do if the color is unknown or a random color?