Android takes xml only from portrait layout folder - java

I have created two XML files for portrait and landscape mode separately and kept them in folders layout and layout-land respectively.
Note: I have given android:launchMode = "singleTask" in manifest file for that activity for some reason.
Issue: In both portrait and landscape mode, it takes xml from layout folder.
What is the reason for taking xml only from portrait layout folder? Is it because of the "single task property"?. What am I missing in this?
Thanks in advance.

Normally, when you change orientation, configuration change event is fired, your activity is destroyed and recreated in the new layout. When it's recreated, the corresponding, portrait or landscape, layout is used.
Because you indicate that you explicitly handle orientation changes, the activity is not destroyed/recreated on orientation change - and therefore the layout is not changed. To achieve what you want, you need to store the original orientation when the app starts and then handle orientation changes in your code, something like this:
private int currentOrientation;
public void onCreate(Bundle sis) {
...
currentOrientation = getResources().getConfiguration().orientation;
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if(currentOrientation != newConfig.orientation) {
//re-set the layout into your activity
setContentView(R.layout.my_layout);
currentOrientation = newConfig.orientation;
}
}
Depending on your logic, you may want to get values from existing views and re-set them after re-setting the layout.

Related

Android - how to use getId() to access orientation specific layout sub views

#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get orientation
LinearLayout layout = isLandscape()
? (LinearLayout) this.findViewById(R.id.main_layout_l)
: (LinearLayout) this.findViewById(R.id.main_layout_p);
Log.i("info", "layout is " + layout.getId());
start();
run();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e("On Config Change",
(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE)
? "LANDSCAPE" : "PORTRAIT");
// added -- this fixes the background not showing
setContentView(R.layout.activity_main);
}
I have two layouts (two files, layout/activity_main.xml, layout-land/activity.xml) for both orientations.
What is to be displayed is slightly different depending on the orientation
ie: portrait won't have some extra panels and some stuff has to be moved around.
I need to access the view programmatically.
When accessing 'layout' I get a NullPointerException
each layout orientation has different ids ending in "_p" or "_l" in the xml file to differentiate whether portrait or landscape, when accessing them in java.
Both xml files are currently LinearLayout->TextView
Either way I cant get them to draw
I am using a thread and a clock to handle the drawing calls. Like in a game.
This is needed for doing some various custom animations.
I don't even think the background is drawing.
If I change from LinearLayout and call the TextView directly by its id
it runs without error, but nothing draws.
Try to remove android:configChanges attribute.
It'd be better not to use android:configChanges attribute.
Please refer to Android Developers Site in details
Caution: Handling the configuration change yourself can make it much more difficult to
use alternative resources, because the system does not automatically apply them for you. This technique should be considered a last resort when you must avoid restarts due to a configuration change and is not recommended for most applications.
https://developer.android.com/guide/topics/resources/runtime-changes

Disable landscape orientation for phones but allow for tablets

So the general consensus is this; most people use their phones in portrait and most people use their tablet in landscape. Depending on which activity it is my app's layout goes crazy when you rotate on the phone to landscape and it just wouldn't be worth the time to fix considering users are unlikely to rotate here and have no reason to do so. I'm aware of the ole orientation="portrait" trick in the Manifest in the activity element, however this locks tablet users into portrait which wouldn't be appropriate. I would like to disable portrait on all my activities for tablet users yet simultaneously disable landscape on most all my activites for phone users. I tried to pull a fast one by making a layout-large-land folder and no layout-large folder, but that doesn't prevent the orientation from changing on tablets.
If you just use setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) from code you will catch interesting effect on Android 26+. If the system autorotation option is enabled and you hold phone in landscape orientation and start new Activity it will appears in landscape orientation and then rotate to portrait in a few seconds. You doesn't catch such effect if set android:screenOrientation="portrait" option in the AndroidManifest. But there are not way to have different rotation option into AndroidManifest for phone and tablet.
There's way to solve that if you wish lock portrait orientation on phone and unlock autorotation on tablet.
Set option android:screenOrientation="locked" in the AndroidManifest for each Activity in you project.
<activity android:name=".SomeActivity"
android:screenOrientation="locked" />
where "locked" – Locks the orientation to its current rotation, whatever that is. Added in API level 18 from Android docs
Then set in parent BaseActivity such code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
int orientation = getResources().getConfiguration().orientation;
if (isTablet()) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
} else if(orientation != Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
There are a few ways to detect that current device is Tablet. Choose implementation of isTablet() method yourself.
I guess you can use a code like this in onCreate() method:
int screenLayoutSize = getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_SMALL || screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
And don't specify any orientation in xml, so by default it switches in both mode.
My suggestion would be to first find the way to know at run-time whether the activity is being executed in a Tablet by invoking a resource as explained in this answer. Then set the orientation as explained in this answer.
-Do One thing put this on the in the res/values file as bools.xml or whatever (file names don't matter here):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
and Put this one in res/values-sw600dp and res/values-xlarge:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
and then into java class file write this below code in onCreate method:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
Devices that are more than 600 dp in the smallest width direction.
see the below link for the how to add directories and file into android studio project

Android - Place fragment over ImageView PROGRAMMATICALLY (NO XML)

I have to add a fragment over an Imageview, but my ImageView goes on top and covers the other views. All this is done in a RelativeLayout.
things must be done dynamically (no xml). I want that my activity has an image, which can be set DYNAMICALLY, and my fragment (added dynamically) should have transparent background, and if this is not true, i can set it to transparent at run time.
This is the code to create the image:
ImageView img=new ImageView(this);
img.setImageResource(imgID);
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
((ViewGroup)findViewById(android.R.id.content)).getRootView()).addView(img);
As you can see, the image works as background, i'm using a ImageView for its scaleType.
Is there a way to do so?
SOLUTION
solved, i added the image to the wrong container.
The function below, however, has been pretty useful. It has been taken from an other answer, and lets a view to get on the back of all the others.
public static void sendViewToBack(View child) {
final ViewGroup parent = (ViewGroup)child.getParent();
if (parent!=null) {
parent.removeView(child);
parent.addView(child, 0);
}
}

How to maintain state of filtered CursorAdapter through orientation changes?

I have an application that helps users organize prescriptions. I have one listview that shows medications and I use an EditText to allow the user to filter the list. The problem I'm having is that the CursorLoader is replaced each time the orientation changes.
From what I understand, the LoaderManager.initLoader() function should be called in onActivityCreated(). In my particular case, I don't have a fragment so I put the initLoader() call inside onPostCreate():
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getSupportLoaderManager().initLoader(MEDICATION_LOADER, null, this);
}
And here is the filter I'm using:
// Set text filter
mMedication.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mMedicationAdapter.getFilter().filter(s);
}
});
I removed the empty beforeTextChanged and afterTextChanged methods to shorten this.
So, what appears to be happening (from using the debugger) is that each time I change the device orientation, initLoader() is called again and the entire list of medications are displayed, not just the filtered ones. Is there a way to implement onSaveInstanceState() to store the current filtered state of the adapter?
Or am I using the text filter wrong? Should I pass the charSequence as a Bundle argument to the loader, or create another loader that handles the text as an argument?
A solution is you can keep the current activity when orientation changes, Just set the Activity to handle config changes in AndroidManifest.xml:
Android config changes
e.g.
<activity
android:name="com.test.MyActivity"
android:configChanges="screenSize|orientation"/>
If your edittext was inflated through a layout file and it has an id; the framework should be automatically save its text.
You could try checking right before you attach your textwatcher, if the edittext has any text inside, then filter your list and then attach your textwatcher.

How to stop whole activity recreation on orientation change

I am new to android. I am doing a sample project on calculation of numbers. And i am using both portrait and landscape layouts. Whenever I change the orientation, my activity is newly created and all the previously entered values get lost. So, I tried to stop activity recreation by android:configChanges="keyboardHidden|screenSize|orientation" and by setting orientation only to android:screenOrientation="portrait". But this makes my portrait layout to fit in landscape mode. But I don't want this. I need to load my separate portrait and landscape layouts on orientation change with same set of values which was previously created(i.e load different layouts without activity recreation).
And also I tried of using overridden methods like onConfigurationchanged, onSaveInstanceState, onRestoreInstanceState. But still values are lost in using onConfigurationchanged method , and activity is recreated in using onSaveInstanceState and onRestoreInstanceState methods (Still the previous values are retrieved here).
Any solution for this?
Thanks in advance.
To resolve this you need to save and retrieve data in/from saved instance state
#Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
// Example to save the value of editText01 in SavedInstanceState
String stateToSave = editText01.getText().toString();
outState.putString("saved_state", stateToSave);
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onRestoreInstanceState(savedInstanceState);
//To Retrieve data from "saved_state"
String stateSaved = savedInstanceState.getString("saved_state");
edittextEditState.setText(stateSaved);
}
}
}
you should look at the onPause{} and onResume{} methods of the activity. because whenever your orientation is changed the activity is paused and then recreated again so you data is lost. and to understand better you should take a look at the activity life cycle
http://developer.android.com/reference/android/app/Activity.html... :)
delete android:screenOrientation="portrait" and give this code, android:configChanges="keyboardHidden|screenSize"

Categories

Resources