I'm trying to create the following design
I sort of did it by using PercentRelativeLayout for layouts and AutoResizeTextView for those TextViews, but I ended up with over 10 layouts and I can see that the layout is very slow being rendered. The main problem were the images because I could get them to do what I want only by doing this sort of things:
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_toLeftOf="#+id/buttonright1layout"
android:layout_centerVertical="true"
app:layout_heightPercent="40%">
<name.company.newapp.PostForm.SelectPhoto.SquareRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerInParent="true">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/btnright2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/me" />
</name.company.newapp.PostForm.SelectPhoto.SquareRelativeLayout>
</android.support.percent.PercentRelativeLayout>
Could anyone suggest a better approach?
Update:
The loading was caused by a large drawable that I had as a background. I removed it and now it's working fine.Since this thread is here I have a few questions about this design:
Will there be any problems if I don't set the size of the TextViews/set it in sp ?(textSize)
<TextView
android:id="#+id/date_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Text4"
android:textColor="#fff" />
Will there be any problems if I set the size of the ImageViews in dp ?
<ImageView
android:id="#+id/img_5"
android:layout_width="#dimen/img_size"
android:layout_height="#dimen/img_size"
android:layout_centerInParent="true"
android:background="#drawable/nexticn" />
There's no problem if you don't specify textSize for TextView. Default value is used.
You can set ImageView width and height in dp without problems. In such case it would be useful to specify a value for scaleType attribute for preventing images to be rendered in a bad way.
I think android:layout_weight is what you're after
Related
I'm building an injection tracking app for diabetics and other people who take regular injections, and I'm trying to align 8 checkboxes on top of an image of a body so the user can specify where they got the injection. The problem is that aligning it right now only works for a very specific screen size, and whenever the size is different, the checkboxes move around and end up not on the correct body part. Is there some way I can accomplish this? Hardcoding the margins doesn't seem to be working well. Any help would be appreciated. Thank you.
Here's what i want it to look like ideally, and here is what it actually looks like on a specific screen size which shifts everything around. It gets more extreme than that of course the larger or smaller the screen size.
and here's my code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.injectiontracker.MainActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/date_and_time_layout"
android:src="#drawable/blank_body" />
<CheckBox
android:id="#+id/abdomen_left"
style="#style/InjectionCheckbox"
android:layout_alignBaseline="#+id/abdomen_right"
android:layout_alignBottom="#+id/abdomen_right"
android:layout_toRightOf="#+id/abdomen_right"
android:layout_toEndOf="#+id/abdomen_right" />
<CheckBox
android:id="#+id/thigh_left"
style="#style/InjectionCheckbox"
android:layout_alignBaseline="#+id/thigh_right"
android:layout_alignBottom="#+id/thigh_right"
android:layout_toRightOf="#+id/thigh_right"
android:layout_toEndOf="#+id/thigh_right" />
<ImageView
android:id="#+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:src="#drawable/ic_save_black_48dp" />
<CheckBox
android:id="#+id/buttocks_left"
style="#style/InjectionCheckbox"
android:layout_below="#+id/abdomen_left"
android:layout_alignLeft="#+id/arm_left"
android:layout_alignStart="#+id/arm_left"
android:layout_marginLeft="24dp"
android:layout_marginStart="24dp" />
<CheckBox
android:id="#+id/arm_left"
style="#style/InjectionCheckbox"
android:layout_marginRight="74dp"
android:layout_marginEnd="74dp"
android:layout_above="#+id/abdomen_left"
android:layout_toLeftOf="#+id/save"
android:layout_toStartOf="#+id/save"
android:layout_marginBottom="16dp" />
<CheckBox
android:id="#+id/buttocks_right"
style="#style/InjectionCheckbox"
android:layout_width="wrap_content"
android:layout_alignBaseline="#+id/buttocks_left"
android:layout_alignBottom="#+id/buttocks_left"
android:layout_toRightOf="#+id/buttocks_left"
android:layout_toEndOf="#+id/buttocks_left" />
<CheckBox
android:id="#+id/arm_right"
style="#style/InjectionCheckbox"
android:layout_alignBaseline="#+id/arm_left"
android:layout_alignBottom="#+id/arm_left"
android:layout_toRightOf="#+id/buttocks_right"
android:layout_toEndOf="#+id/buttocks_right" />
<CheckBox
android:id="#+id/abdomen_right"
style="#style/InjectionCheckbox"
android:layout_marginLeft="55dp"
android:layout_marginStart="55dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<CheckBox
android:id="#+id/thigh_right"
style="#style/InjectionCheckbox"
android:layout_marginTop="11dp"
android:layout_below="#+id/buttocks_left"
android:layout_alignLeft="#+id/abdomen_right"
android:layout_alignStart="#+id/abdomen_right" />
I think what will help you the most here is PercentFrameLayout.
This is a support library so you have to add
compile 'com.android.support:percent:24.2.1'
to your build.gradle file (the version will vary depending on what you've updated).
Your current layout uses wrap_content for the width and height of the ImageView. If your screen width is smaller that the width of the image, then the ImageView is going to have a different aspect ratio than the image itself, and this is going to make getting an accurate layout difficult.
A good approach is to have at least two layouts
one layout for smaller devices like phones where the screen width may be smaller than your image
another layout for larger devices like tablets where the screen width is larger than your image
See How to support multiple screens if you aren't familiar with alternate layouts.
First you need to ensure that the aspect ratio of the ImageView matches the image. Do this by specifying android:adjustViewBounds="true" along with a width of match_parent and a height of wrap_content.
Then wrap the ImageView in a PercentFrameLayout that also has a width of match_parent and a height of wrap_content.
Now you have a view that is somewhat predictable for using percentages. I downloaded the image that you linked to and used it to come up with this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.percent.PercentFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/blank_body" />
<CheckBox
android:id="#+id/abdomen_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="15.5%"
app:layout_marginTopPercent="32%"/>
<CheckBox
android:id="#+id/abdomen_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="25%"
app:layout_marginTopPercent="32%"/>
<CheckBox
android:id="#+id/thigh_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="15.5%"
app:layout_marginTopPercent="47%"/>
<CheckBox
android:id="#+id/thigh_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="25%"
app:layout_marginTopPercent="47%"/>
<CheckBox
android:id="#+id/arm_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="57%"
app:layout_marginTopPercent="22%"/>
<CheckBox
android:id="#+id/arm_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="82.5%"
app:layout_marginTopPercent="22%"/>
<CheckBox
android:id="#+id/buttocks_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="64%"
app:layout_marginTopPercent="38.5%"/>
<CheckBox
android:id="#+id/buttocks_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_marginLeftPercent="73.5%"
app:layout_marginTopPercent="38.5%"/>
</android.support.percent.PercentFrameLayout>
</RelativeLayout>
(Sorry, I remove your styles and such since I didn't have access to those.)
For the larger devices, your alternate layout should specify a fixed width for the PercentFrameLayout:
<android.support.percent.PercentFrameLayout
android:layout_width="600dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
then you would position this within your larger RelativeLayout as you require (I show center/top as an example).
This should get you a pretty acceptable result.
You will still see some slight distortion depending screen width since you are measuring to the left and top of the checkbox. For a pixel-perfect layout, you would need to make a custom layout component that can position the centers of the checkboxes right at the points of interest.
that is my problem in relative-layout:
i have some image views that some part of each imageview is out of
display with negative margin.
i design this layout in a display dimension that shown in left side
and that is OK.
but in other display demensions some parts of views that i dont want
to be shown will be shown [like right image]. (or in smaller
displays some parts not shown).
so. i want just wanted box of layout will be visible in different
display sizes and be scaled according to display dimensions.
Sorry i know the problem is involved ;)
i need just visible part of layout scaled in various display sizes, also want views be separate to animate them.
that is one arrows sample code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="4000dp"
android:layout_height="300dp"
android:rotation="15"
android:src="#drawable/rectangle"
android:layout_row="0"
android:layout_column="0"
android:id="#+id/img_rct_header"
android:layout_marginBottom="108dp"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_marginLeft="-100dp"
android:layout_marginTop="-160dp"
android:layout_marginRight="-120dp"
android:clipChildren="false"
android:scaleType="fitXY" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="135dp"
android:rotation="195"
android:src="#drawable/arrow_tall"
android:id="#+id/img_arw_in_sore"
android:scaleType="fitXY"
android:layout_marginTop="815dp"
android:clipChildren="false"
android:layout_marginRight="-8450dp"
android:layout_marginLeft="25dp"
android:visibility="gone" />
<ImageView
android:layout_width="500dp"
android:layout_height="150dp"
android:rotation="195"
android:src="#drawable/arrow_svg"
android:id="#+id/img_arw_in_tafsir"
android:scaleType="fitXY"
android:layout_marginBottom="-50dp"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_marginLeft="161dp"
android:layout_marginTop="360dp"
android:layout_marginRight="-1150dp"
android:clipChildren="false"/>
<ImageView
android:layout_width="500dp"
android:layout_height="150dp"
android:rotation="195"
android:src="#drawable/arrow_svg"
android:scaleType="fitXY"
android:id="#+id/img_arw_out_tafsir"
android:layout_marginBottom="0dp"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_marginLeft="-272dp"
android:layout_marginTop="240dp"
android:layout_marginRight="55dp"
android:clipChildren="false"/>
<ImageView
android:layout_width="4000dp"
android:layout_height="320dp"
android:rotation="15"
android:src="#drawable/rectangle"
android:layout_row="0"
android:layout_column="0"
android:id="#+id/img_rct_footer"
android:layout_marginBottom="-800dp"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_marginLeft="-100dp"
android:layout_marginTop="550dp"
android:layout_marginRight="-120dp"
android:clipChildren="false"
android:scaleType="fitXY" />
</RelativeLayout>
thanks for your help ;)
Your layout is pretty complex. If all you want is to have this as a background that will look the same in different screen sizes, I'd suggest that you draw that background separately, save it as a high quality png, and then put it in one ImageView, without all the hassle of margins and rotation.
You must set the background of layout to that picture in order not to show it in dp.
The dp size is like the pixel of screen and its getting smaller and bigger in other devices try using the value match_parent instead of 4000dp
The best way is to use apps like picsart or picsay. Just put all the pictures in one picture edit the picture then make that the background of the whole layout with these values
layout_width="match_parent"
layout_height="match_parent"
but if you want to animate them you must add the layout to another layout
and give them layout_weight
I am updating my Android app and realized that I have created a layout for every possible screen size (layout-small, layout-large, etc...) It would be a huge pain to go through every XML file and manually make a small change. I am attempting to create a single XML file to support all screen sizes. After reviewing the Android documentation and other questions on stackoverflow, it seems LinearLayout is the best choice as you can provide a weightSum and layout_weight for each item in the layout. This is not working as expected (see below code and images). I am doing this correctly? Do I have to go back to creating a RelativeLayout for every possible screen size?
My images are an a single drawable folder and my layouts are in a single layout folder.
XML
<?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:background="#drawable/bg"
android:gravity="center"
android:orientation="vertical"
android:weightSum="100" >
<ImageButton
android:id="#+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/image0"
android:background="#null"
android:layout_weight="30" />
<ImageButton
android:id="#+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/image1"
android:background="#null"
android:layout_weight="30" />
<ImageButton
android:id="#+id/key"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="30"
android:background="#null"
android:src="#drawable/image0_key" />
<TextView
android:id="#+id/tvScore"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Score: 0"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_weight="10"
android:layout_gravity="left" />
</LinearLayout>
Resulting View (overflow of items and layout not consistent for screen sizes)
Nexus One:
Tablet:
EDIT:
I have added the following drawable-____ folders. It produces the same result.
You might want to consider creating compatibility layout folders. :)
Yes we have a solution for the same by using android's percent layout we can now use app:layout_heightPercent and app:layout_widthPercent to fit all the screens using single layout.
compile 'com.android.support:percent:23.0.0'
Why use LinearLayout weight property now we have simpler solution.
Demo HERE !
GitHub project HERE !
Consider a simple sample
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/fifty_huntv"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ff7acfff"
android:text="20% - 50%"
android:textColor="#android:color/white"
app:layout_heightPercent="20%"
app:layout_widthPercent="50%" />
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_toRightOf="#id/fifty_huntv"
android:background="#ffff5566"
android:text="80%-50%"
app:layout_heightPercent="80%"
app:layout_widthPercent="50%"
/>
</android.support.percent.PercentRelativeLayout>
Hope it's useful for someone :-)
Use Below layout for arranging your ImageButton and TextView. It works for all screen size Layouts.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="3" />
<ImageButton
android:id="#+id/imageBtn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/ic_launcher" />
<ImageButton
android:id="#+id/imageBtn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/ic_launcher" />
<TextView
android:id="#+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Score: 0" />
</LinearLayout>
Never put an weight sum like hundred ,just try using single digits
DisplayMetric dm =new DisplayMetric();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int h= dm.heightPixels;
int w= dm.widthPixels;
h=h/10; // 10 is for example for 10% of display height
w=((w*20)/100); // 20%of display width
LinearLayout.LayoutParams params= new LinearLayout.LayoutParams(w,h);
YourObject.setLayoutParams(params);
//(YourObject) can be everything such as button , image button, textview,...
There are two issues here, one is to fill the size of the screen and the other is supporting the various resolution sizes of mobiles. Even within xxxhdpi, there are variations as new flagship Samsung Mobiles are drifting to 19.5 x 16.
Linear layout along with weight attributes does give a good coverage but beware of the nested tags and performance. It worked out well for most of the scenarios I have handled.
In addition, as pointed out in other answers, different drawables/resources for the standard sizes helps maintaining similar view in all devices.
I want to have two buttons at the top of my program taking users to different activities. I'm having a lot of trouble with the formatting.
How can I make it so that the buttons will stretch proportionally based on the screen size? Right now, they will look OK for one screen size, then I will switch to a different one and it will appear all smushed or stretched. I've tried all of the different ScaleTypes and none seem to make a difference. I also went though and proportionally saved all of the images to the correct sizes regardimg xhdpi, hdpi, etc using Shubhayu's answer.
Here's my code so far:
<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"
android:background="#drawable/brushed_metal_background_dark"
tools:context=".HomeActivity" >
<ImageButton
android:id="#+id/incidentsSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/incident_bar2"
android:contentDescription="Incidents"
android:onClick="chooseIncident"
android:scaleType="center" />
<ImageButton
android:id="#+id/operationalPeriodsSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/operationalperiod_bar2"
android:contentDescription="Operational Periods"
android:onClick="chooseOperationalPeriod"
android:scaleType="fitCenter" />
Change android:background to android:src that will keep the aspect ratio. Use android:scaleType="centerInside" to fit whole image inside button area and optionally use android:adjustViewBounds=true to remove empty spaces. Example:
<ImageButton
android:id="#+id/incidentsSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="Incidents"
android:onClick="chooseIncident"
android:src="#drawable/incident_bar2"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
<ImageButton
android:id="#+id/operationalPeriodsSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="Operational Periods"
android:onClick="chooseOperationalPeriod"
android:src="#drawable/operationalperiod_bar2"
android:scaleType="centerInside"
android:adjustViewBounds="true"/>
I am guessing that you are trying to size the buttons evenly on the top of the screen. If that's the case then you should set android:layout_width="0dp".
Just use android:layout_width = "wrap_content"
My layout contains 3 ImageButtons, arranged vertical in a LinearLayout.
Now I want that each of them has the same height and together fill the device's screen height.
Works fine with the attribute android:layout_weight="1". But if the image of one ImageButton is too big, it won't work (this button is higher than the others), despite setting android:scaleType="center_inside".
Any advices/tricks?
If you need any code, let me know. But there is nothin special.
If you have given weights correctly than this should work. The size of the image doesn't matter than. Just one thing to keep in mind while using weights is that attribute for which you are giving the weight(height/width) should be assigned value "0dp" in the xml, only then the weights will work correctly. Here is the example code.
<?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:gravity="center"
android:weightSum="3">
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:src="#drawable/drawable1"
android:layout_weight="1"
android:scaleType="centerInside"
/>
<ImageView
android:id="#+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:src="#drawable/drawable2"
android:scaleType="fitXY" />
<ImageView
android:id="#+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:src="#drawable/drawable3"
android:scaleType="fitXY" />
</LinearLayout>
Just use this xml and replace the drawables according to your needs. Let me know if any issues.