Android: View.fitSystemWindows() not called - android

When I switch from landscape to portrait mode, View.fitSystemWindows() is not called. Therefore my view becomes offset with no reason because the navigation bar is not at the same place as it used to be :-(. I tried calling View.requestFitSystemWindows() but that did not make anything. Any idea what could be wrong ?

I workarounded that by calling setPadding manually
#Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setPadding(0, 0, 0, 0);
}
Not sure this is the nicest solution but it works for me...

Related

How to retain state of activity after animation upon something like screen rotation?

So for example I use an object animator to change the alpha of a button to 0 and then I rotate the screen, then it's back to pre animated state because onCreate is called again. I was thinking I should implement something like an animation listener and at the end of the animation I should change the properties of the button, but I am not sure how to do that. For example if I have a constraint layout and I moved a button by 100 pixels up, what code should I have in the animation listener so that the change stays after the animation is over. I read something about setting the fill after tag to be true but I believe that is for view animations.
Thank You for the help.
For the application you've described, you could use a ValueAnimator and set an AnimatorUpdateListener on it to record the state after each animation frame.
To listen for orientation changes and persist the state of the animation, you should first include android:configChanges="orientation" within the <activity> tag of your Manifest. This will ensure that your activity is not recreated on orientation change and that onCreate() won't be called again. Whenever an orientation change occurs, onConfigurationChanged() will be called, so you should override it to persist the animation state.
So, in your onCreate() you could do something like:
ValueAnimator valueAnimator = ValueAnimator.ofObject(new IntEvaluator(),
initialPosition, finalPosition);
valueAnimator.setDuration(duration);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// mCurrentPosition should be a member variable
mCurrentPosition = (int)animation.getAnimatedValue();
// Update the position of your button with currentPosition
}
}
valueAnimator.start();
and your onConfigurationChanged() should look like:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.your_layout);
// Set the position of your button with mCurrentPosition
}
For more info, please refer to https://developer.android.com/reference/android/animation/ValueAnimator.html and https://developer.android.com/guide/topics/resources/runtime-changes.html.

Custom view (swipeView) not resizing properly after orientation change

I'm using SwipeView (http://jasonfry.co.uk/blog/android-swipeview/) inside my activity's layout to display several pages. Moreover, I want to handle the orientation changes manually so I added
android:configChanges="orientation|keyboardHidden|screenSize"
into the application's manifest, so that onDestroy/onCreate are not called. Unfortunately, by doing this, the elements inside the swipeview are not resized accordingly. I already tried the following methods:
invalidate
requestLayout
forceLayout
None of them did the trick!
Any help would be appreciated.
Thanks
In case anyone struggles with this, I finally found a solution.
The trick was to request layout not on the swipeview itself but rather on getChildContainer().
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
SwipeView swipeView = (SwipeView)findViewById(R.id.swipeView);
int pageWidth = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
swipeView.setPageWidth(pageWidth);
for ( int i = 0; i < swipeView.getChildContainer().getChildCount(); i++ )
swipeView.getChildContainer().getChildAt(i).getLayoutParams().width = pageWidth;
swipeView.getChildContainer().requestLayout();
swipeView.scrollToPage(swipeView.getCurrentPage());
}

replace layout on orientation change

My app has a webview and some buttons inside a LinerLayout.
the problem is, I want the buttons to be on bottom in portrait mode and on left in landscape mode while the webview maintains it's state.
Two different layout doesn't work as it force recreation of the activity that refresh the webview. for now I use android:configChanges="orientation" in activity tag so webview doesn't get refreshed on orientation change.
Is there anyway to replace the layout of buttons on the change of screen mode?
portrait mode
landscape mode
I tested fragments, but dealing with fragment makes things much more complex and the fragment itself needs saving and restoring which may not work in a webview which has javascript state, So I searched more and find a nice article somewhere and with some modification I came to a solution which I suggest:
First, add android:configChanges="orientation|screenSize|keyboard|keyboardHidden" so the app handles the config changes instead of android.
Make two different layout for landscape and portrait. In both layouts instead of webview place a FrameLayout which acts as a placeholder for the webview.
Define initUI method like this and put everything related to UI initialization in this method:
public void initui()
{
setContentView(R.layout.main);
if (wv == null) wv = new WebView(this);
((LinearLayout)findViewById(R.id.webviewPlace)).addView(wv);
findViewById(R.id.home).setOnClickListener(this);
}
If the webview doesn't exist yet it will be created and after setContentView(R.layout.main) it will be added to the layout. Any other UI customization you need came after this.
and in onConfigurationChanged:
#Override
public void onConfigurationChanged(Configuration newConfig)
{
((LinearLayout)findViewById(R.id.webviewPlace)).removeAllViews();
super.onConfigurationChanged(newConfig);
initUI();
}
In onConfigChange the webview is removed from old placeholder and initui will be called which will add it back to the new layout.
In oncreate() call initui() so the ui will be initialized for the first time.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
initUI()
}
I wish it would be helpful for someone.
If you are using android:configChanges="orientation|screenSize"
In manifest,it ignores the XML in "layout-land". If you create a different XML for landscape don't use the android:configChanges="orientation|screenSize" tag for that activity in manifest.
put that at layout-land for the layouts you want as landscape.
The idea is, you shouldn't really use configChange="orientation" because it has its downsides. You can find a detailed post here . You should manually handle your state if you want to change your layout. Of course you can programmaiclly do this but if you want to use xml to do this. You can maintain you webView with fragments.
Try to use this code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.activity_splash);
}
Make your view a relative layout. When the orientation changes just adjust the layout params for each view in code.
Have your buttons be contained in a linear layout
As in..
Portrait
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
buttonLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
buttonLinearLayout.setLayoutParams(lp);
LayoutParams webParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.ABOVE, R.id.buttons);
webView.setLayoutParams(webParams);
Landscape
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
buttonLinearLayout.setOrientation(LinearLayout.VERTICAL);
buttonLinearLayout.setLayoutParams(lp);
LayoutParams webParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
lp.addRule(RelativeLayout.TO_RIGHT_OF, R.id.buttons);
webView.setLayoutParams(webParams);
Make sure the LayoutParams you are using are the RelativeLayout params (always use the Layoutparams of the view's parent)
Add in the manifest
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="#string/app_name">
and
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Resources.getSystem().getDisplayMetrics().widthPixels>
Resources.getSystem().getDisplayMetrics().heightPixels)
setContentView(R.layout.activity_layout1);
else setContentView(R.layout.activity_layout2);
...
}
and
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.activity_layout1);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.activity_layout2);
}
}
Documents here:
https://developer.android.com/guide/topics/resources/runtime-changes.html
You can add values-(configuration that you require - eg. land,portrait) folder under resources and mention the layout you need for this configuration.. It's as simple as that.
Please checkout the below link for further information-
http://developer.android.com/training/multiscreen/screensizes.html#TaskUseAliasFilters

Position view below action bar with overlay

I would like to position a view below an action bar with overlay. Is there a way of doing this via XML layout?
I would like to avoid using constants as there are already at least 4 possible values and that number is likely to grow.
Compatibility with ActionBarSherlock is a plus.
android:layout_marginTop="?attr/actionBarSize"
This will account for changes in size based on screen configuration automatically. You can see a demo of its use in the "Overlay" example of the 'Demos' sample that comes with ActionBarSherlock.
Jake Wharton's answer does not work if you're handling configuration changes.
This is how I solved this problem by code, in case it helps anyone:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
layoutTheView();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
layoutTheView();
}
private void layoutTheView() {
ActionBar actionBar = this.getSupportActionBar();
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) mTheView.getLayoutParams();
int actionBarHeight = actionBar.getHeight();
params.setMargins(0, actionBarHeight, 0, 0);
mTheView.setLayoutParams(params);
mTheView.requestLayout();
}
use padding top
android:paddingTop="50dp"

Getting width during build of an Activity

I have a problem, and I can't seem to figure out what to do about it.
I'm new to developing with Android, but I have experience with Java.
During the onCreate(bundle), onPostCreate(bundle) or any other similar method, I can't get the correct width of a View. It returns 0. I also made a simple button for debug purposses, and that button returns the correct value.
How do I call a method that gets the width of a View after the onCreate method?
If that's not possible, what is a workaround?
Thanks in advance,
Gerralt
The problem is because, you are trying to find out the width as soon as you you start your activity.
But at this position the actual transformation of your view wouldn't have occurred. Android provides a special callback to find the width and height of all individual views. To access it, you have to override the onWindowFoucsChanged() method. Here is a sample,
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
System.out.println("...Height..."+textview.getMeasuredWidth());
}
This line textview.getMeasuredWidth() helps you to find the actual width of the textView at runtime. Similarly you can find the width and height for any view using this method.
As i think, you are in the onCreate(Bundle) method:
public void onCreate(Bundle xxx) {
super(xxx);
// init some stuff here
setContentView(R.layout.my_layout);
// from THIS point you can get sizes of Views
}
Sorry if i'm wrong, but on my project it works. OK, i have to say i use often
custom views and use sizes not in my activity code but in View code.
Do this is onWindowFocusChanged() like this:
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus && llfullscreen!=null){
int layoutHeight = llfullscreen.getHeight();
ViewGroup.LayoutParams params = lv.getLayoutParams();
params.height = lv/2; //Set to half the screens size
this.lv.setLayoutParams(params);
this.lv.invalidate();
}
}

Categories

Resources