Knowing layout used at runtime - android

I have two android devices for testing. One is with resolution 480x320 and other is with 800x480. I define different layouts in layout-normal and layout directories. I also tried it with layout-hdpi, layout-mdpi etc different combinations.
Is there a way to know from the log of somewhere that in which layout category a device falls just for debugging purposes. I would like to know layout file from which directory is used at runtime. If not then could someone tell me the right combination of layout directories for two devices with the pre-mentioned resolution.
Thanks in advance.

To find which layout (from layout-ldpi, layout-mdpi folder etc...) is used during runtime. You can use the tag attribute on your layout. For example let's say you have defined two layouts for different screens, the one in layout-mdpi folder and the other in layout-hdpi folder. Something like this:
<?xml version="1.0" encoding="utf-8"?>
<!--Layout defined in layout-mdi folder-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/MainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:tag="mdpi"
android:orientation="horizontal" >
<!-- View and layouts definition-->
<!LinearLayout>
And:
<?xml version="1.0" encoding="utf-8"?>
<!--Corresponding Layout defined in layout-hdi folder-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/MainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:tag="hdpi"
android:orientation="horizontal" >
<!-- View and layouts definition-->
<!LinearLayout>
To check which layout is used during runtime, you can use something like this:
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.MainLayout);
if(linearLayout.getTag() != null) {
String screen_density = (String) linearLayout.getTag();
}
if(screen_density.equalsIgnoreCase("mdpi") {
//layout in layout-mdpi folder is used
} else if(screen_density.equalsIgnoreCase("hdpi") {
//layout in layout-hdpi folder is used
}

Here is an extension of #Angelo's answer that may work depending how you are using your elements: in each file, if you have the same element that you don't need to manipulate, you can give it a different ID for each layout you define (as opposed to tagging it).
For example, say I don't need to manipulate the base linear layout, I only need to manipulate the views inside it.
Here is my hdpi layout:
<?xml version="1.0" encoding="utf-8"?>
<!--Corresponding Layout defined in layout-hdpi folder-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout-hdpi"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- View and layouts definition-->
</LinearLayout>
Heres an mdpi layout:
<?xml version="1.0" encoding="utf-8"?>
<!--Corresponding Layout defined in layout-mdpi folder-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout-mdpi"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<!-- View and layouts definition-->
</LinearLayout>
And here is my code that decides which layout it is:
if ( findViewById(R.id.layout-hdpi) != null ) {
//we are in hdpi layout
} else if ( findViewById(R.id.layout-mdpi) != null ) {
//we are in mdpi layout
}
The idea is that only one of the ids that you define for that item accross your different files will actually exist, and whichever one does is in the layout that actually loaded. The caveat is that if you actually need to manipulate that item later on, this method makes for a lot of extra work and is probably not ideal. You wouldn't want to use this technique on an item such as an EditText because then you have to check which layout you are in to decide which id to use to get that edit text.

Related

How to make title of PreferenceScreen resizable?

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="#string/game_title">
I've a preference screen for my app for which I've added the title. When the app gets opened in split screen and resized to different size in window, the title is disappearing when the width present is smaller.
Tried adding,
android:layout_height="wrap_content"
android:layout_width="wrap_content"
property to the PreferenceScreen but it didn't help. Some help would be appreciated.
Like in this answer, you can create a custom layout for the PreferenceScreen and apply it with android:layout attribute
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:layout="#layout/preference_title"
android:title="#string/game_title">
preference_title.xml layout
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="#dimen/preference_title"/>
And create different versions of res/values/dimen.xml file to have variable value of the title text size (#dimen/preference_title) that are proportional to possible screen widths .. typically you'll have different versions values directory, for instance for a screen width of w600dp, you'll have values-w600dp directory.

Resource ID of Button Defined Using Include Directive in Layout XML

I came across an app, whose layout puzzles me.
Assume two layout XML files, such that one includes the other:
activity_button.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="#layout/button"/>
</LinearLayout>%
button.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/button"
android:onClick="sendMessage">
</Button>
What is the resource ID of the button?
I thought one always had to specify ID via android:id attribute, so I am confused why this layout works. I also checked the R.java ID entry and it seems to be empty.
android:id
Is not mandatory field for a view in the layout xml file. the only two mandatory fields are the width and height of the view.
Think of situations when you want a layout to simply show some title without any business need to change it through the activity life time. for this need you don't need to obtain this view id, and don't need the overhead of creating id for this view
What is the resource ID of the button?
Doesn't have one
I thought one always had to specify ID via android:id attribute
Why did you think this? You often leave off this attribute for the root views of most layouts. (See LinearLayout of your question)
You do not need an android:id if you never expect to find the view using an ID. Since the onClick is defined in the XML, there's really no purpose in finding the button.

Landscape ViewPager

When I change my orientationon landscape my photo will be only half ... I want when I change my orientation to be like on facebook , to show full picture .
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
You have to create another layout for horizontal layout. if you want your portrait view to be different from your landscape view. you must create another XML file for landscape.
The two XML file will be handled by the same JAVA code. although you can programmatically listen to orientation change but would prefer the different layout for Different Orientation.
create two types of layout directories to handle orientation . layout-land layout-port put the xml with the same name in both the directory. example if you have main.xml file then add have to put it in both directory.
Documentation on supporting multiple screen

How to handle 2 different layouts in an activity Android

[Edited]:
I have already developed one application which works well on different screen size phones and tablets, I followed as per android guidelines to create the different sets of UI layouts to cater with different sizes of screens(phones and tablets) and all layouts will be in portrait mode. Everything works fine till then but now I got one new requirement where the layouts of tablets will be changed i.e. it will be having some extra information than phone layouts and all new layouts will be in landscape mode.
Now my doubts are:
In old implementation, all layouts name are same in different layout folders i.e. layout,layout-small,layout-large etc... so , as per new requirement, all layouts of large and extra-large should be in landscape mode but if i keep the same name of layout then how do I handle the orientation? At present, orientation attribute mentioned in manifest file for each activity.
If I keep the different name of these layouts then I have to handle at run time i.e. while loading the activity,based on checking on phone screen size and then load the respective layout, so same activity can load different layout based on checking screen size. Will it be a optimal approach to do so?
OR,Do I have to altogether introduce new activities for all new layouts to handle this scenario?
Please suggest me best approach to handle this scenario.
A good point to start on this would be official Android documents (below links).
http://developer.android.com/guide/practices/screens_support.html
http://developer.android.com/training/basics/supporting-devices/screens.html
In a nutshell I can tell you would have to create multiple layouts to address your requirement for supporting multiple screen sizes/resolution. Within your application source directory you will have to create a different layout xml (with same name) under different resource-layout-directories as shown below:
res/
layout/ # default (portrait)
main.xml
layout-land/ # landscape
main.xml
layout-large/ # large screen devices (portrait)
main.xml
layout-large-land/ # large screen devices (landscape)
main.xml
I would suggest you to name all similar files with the same name.
Take full advantage of the qualifiers provided by Android like the size, or the set width qualifier. You may have a single pane layout for small screen phones and multi pane layout for tablets. It's a good advice to provide multi pane layout ( you may combine two existing layouts into one ) for landscape orientation.
For example :
res/layout/onepane.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:id="#+id/frag1"
android:layout_height="fill_parent"
android:name="com.example.android.dummyApp"
android:layout_width="match_parent"
android:background="#drawable/bg"/>
</LinearLayout>
res/layout/twopanes.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<fragment android:id="#+id/fragone"
android:layout_height="fill_parent"
android:name="com.example.android.dummyApp"
android:layout_width="400dp"
android:layout_marginRight="10dp"
android:background="#drawable/bg"/>
<fragment android:id="#+id/fragtwo"
android:layout_height="fill_parent"
android:name="com.example.android.dummyApp"
android:layout_width="fill_parent" />
</LinearLayout>
Now that all possible layouts are defined, it's just a matter of mapping the correct layout to each configuration using the configuration qualifiers. You can now do it using the layout alias technique:
res/values/layouts.xml:
<resources>
<item name="main_layout" type="layout">#layout/onepane</item>
<bool name="has_two_panes">false</bool>
</resources>
res/values-sw600dp-land/layouts.xml:
<resources>
<item name="main_layout" type="layout">#layout/twopanes</item>
<bool name="has_two_panes">true</bool>
</resources>
Note : The bool values in the two xml files in values folder.
The Smallest-width qualifier allows you to target screens that have a certain minimum width given in dp. Instead of the large size qualifier, use sw600dp to indicate the two-pane layout is for screens on which the smallest-width is 600 dp.
Also, another solution:
If you are planning to make different activities for different screen sizes, you can build multiple apk for the same project. There should be a separate Android project for each APK you’re going to release.
Please look at this link for more information on Multiple APKs.
http://developer.android.com/training/multiple-apks/screensize.html
Personally, I'd make two different Fragments, with two different Fragment Layouts, and I'd load the Fragment for the right screen size based on the layout folder identifier, like so: http://developer.android.com/training/basics/supporting-devices/screens.html
Typical Fragment:
public class MyFragment extends Fragment implements View.OnClickListener
{
private Button btnSave;
private Button btnCancel;
public MyFragment()
{
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_myfragment_small, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
btnSave = (Button) getActivity().findViewById(R.id.myfragment_small_save);
btnCancel = (Button) getActivity().findViewById(R.id.myfragment_small_cancel);
btnSave.setOnClickListener(this);
btnCancel.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
if (btnSave == v)
{
save();
}
else if (btnCancel == v)
{
cancel();
}
}
}
And do the same thing for the larger one. Bonus points if you reuse the save() and cancel() function by extending from MyFragment, or by ripping out the logic of them into another class.
Static fragment linking:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/fragment_myfragment_small"
android:name="com.example.stuff.longer.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
And the layout for the fragment in fragment_myfragment_small.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button android:id="#+id/myfragment_small_cancel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="#string/cancel"
/>
<Button android:id="#+id/myfragment_small_save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/myfragment_small_cancel"
android:text="#string/save"
/>
</RelativeLayout>
And make a second one for the second, larger layout. Place the layout in a different \res\layout folder, such as \res\layout-large.

Landscape resource not picked up via LayoutInflater

I am trying to dynamically add buttons to table rows, but need to alter the style of the buttons based on screen orientation. I have the following "game_answer_button.xml" layout file in both "layout" and "layout-land" folders.
res/layout:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
/>
res/layout-land:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
style="#android:style/Widget.Button.Small"
/>
The button layout is being inflated in my activity as follows:
LayoutInflater inflater = getLayoutInflater();
Button button = (Button)inflater.inflate(R.layout.game_answer_button, null);
button.setText(image.getDescription());
However, it seems the default (portrait) layout is selected every time. If the contents of the default layout are replaced with the landscape layout, then the landscape layout is finally rendered. It doesn't seem to be correctly selecting the landscape layout resource via LayoutInflater.
Any ideas on this?
did you check if the configuration of the activity, where the button is used, in the manifest is set to portrait only?
I found the problem. I was loading the dynamic buttons to an ArrayList and merely adding the buttons to my parent view on each configuration change--meaning the button style would have already been inflated when pulling the button objects from "cache". Just another Dev "doh!" moment.

Categories

Resources