I want to achieve the following:
It works with the following layout:
<?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="horizontal">
<LinearLayout
android:layout_weight="3"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
android:name="com.bobjohn.DetailsMenuFragment"
android:id="#+id/detailsMenuFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="6"
/>
<fragment
android:name="com.bobjohn.SummaryFragment"
android:id="#+id/summaryFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:layout_weight="4"/>
</LinearLayout>
<TextView
android:layout_width="0dp"
android:layout_weight="7"
android:layout_height="fill_parent"
android:text="Test Text"/>
</LinearLayout>
However, I get the warning about nested weights being bad for performance. I understand the error but I don't know how to express this layout in another way. What is the alternative?
There are NEW updates in SUPPORT Libs, Please check Accepted Answer too.
Updated Answer :-
Whenever you create any view, It calls it's measure events to know the height width of view on the screen, If you are not using WRAP_CONTENT or FILL_PARENT or FIXEDSIZE and using Weights then it's becoming more complex to render your layout on the screen.
Means,
First your main layout is rendered and calls it's measure..then based on weight all child views calls it's measure events recursively so it consumes more time to load.
So, One should avoid nesting of weights.
Alternative to Nested weights :-
You should consider using different layout and drawable folder specific to different sizes. Write your views in your XML with specific height-width OR make it wrap_content and use specific background images OR make it fill_parent.
I believe that as developer we may be wrong several time, but as creator Android (Lint) they may be wrong only in rare case, should listen to those warnings to make your code better.
BELOW ANSWER WAS WRITTEN WITH LACK OF KNOWLEDGE ABOUT ANDROID LAYOUT
AFAIK, I think you have done right, this is the best written XML for the same.
You have used the weight attribute perfectly as it should have been used. You just ignore the Warnings.
What is the alternative?
I have coded all my XML in the same way in my projects so This has been the best alternative to me,So I dont think there is any other alternative to CODE the XML to get Such layout until and unless you use RelativeLayout as parent layout with some fixed sizes height and width of the child views. Still I advice you keep it as it is.
I would have deleted this answer as I still don't completely know Android Layouts but keeping it to receive new comments and answer based on this
Yes we have the alternative for nested LinearLayout weight by android's percent support library
Code and concept HERE !
GitHub Project HERE !
Consider this simple layout where I have totally avoided weight property of LinearLayout
<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>
Really awesome !!!
I think (and I will probably be flamed for this), but again I think my phone has a quad core processor to rival (if not utterly destroy) most peoples home PC's.
I also think this kind of hardware capability is the future of phones.
So I come to a conclusion, that as long as you are not getting carried away with nesting (in MHO a layout should never be more then 4 levels deep, and if it is you are probably doing it wrong), your phone could care less about having weights.
There are many things you can do that will have a much more far reaching effect on performance, then worrying about your processor doing some extra math.
(please note that I am being slightly humorous, and so not to take anything too seriously from this post, other then the idea that there are other things you should optimize first, and that worrying about a 2-3 level deep weight is not helping your health)
Related
I'm trying to make an app (well, part of an app) which takes an input string from the user and displays it fullscreen, in a different fragment. Which I've got working, but using autoSize on it makes the text so big it gets wrapped, like this:
Not all words get broken if they're small enough:
Looking through the docs (and some web searching), these were the only XML attributes that seemed relevant:
android:breakStrategy="simple"
android:ellipsize="none"
android:hyphenationFrequency="none"
None of them seemed to change the behaviour. About the only thing I could find that makes a difference is android:singleLine="true" but that makes things worse:
and I'm not sure I want to know how much worse that makes it when there's multiple words.
I've pared the fragment layout down to basically the minimum possible that I can think of:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<TextView
android:id="#+id/frag_big_text_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/big_text_background"
android:gravity="center"
android:keepScreenOn="true"
android:clickable="true"
android:longClickable="true"
android:focusable="true"
android:textColor="#color/big_text_foreground"
android:breakStrategy="simple"
android:ellipsize="none"
android:hyphenationFrequency="none"
app:autoSizeTextType="uniform"
app:autoSizeMaxTextSize="240sp"
app:autoSizeMinTextSize="14sp"
app:autoSizeStepGranularity="1px"
tools:gravity="center"
tools:targetApi="m"
tools:text="BIG TEXT HERE"/>
</FrameLayout>
I know I could set the autoSizeMaxTestSize to something lower that should fit most phone screens, but then it won't fill the screen on a tablet (and don't worry about targeting m, my AVD is set to match the specs of my phone, which is on API 29). The code that sets the current text is also pretty simple:bigTextView.text = messageList[index] (and it's definitely not a problem with the list it's pulling from, since I tried hard coding it with bigTextView.text = "thisisareallylongword", same result).
I'm hoping this is one case where I'm missing something obvious and don't have to reinvent the wheel. Wheels aren't my area of expertise, I figured that out when I had to fix a broken pip install.
But whatever reinvention or stupid intervention is required, can anyone help me out?
I'm trying to create the layout part of my app. I wanna know the best approach of going about this section.
I'm thinking of going with something like this, but i think its too much for just displaying three elements
This is a common practice for displaying similar layout. If you want, you can replace all nested layout to ConstraintLayout. It can improve code extensibility, but it can slightly slow down the rendering speed of the UI.
As a result, I think your current variant is the most optimal.
Yeah, thats fine but for the ImageView you will also need to nest it inside a CardView
<androidx.cardview.widget.CardView
android:id="#+id/one"
android:layout_width="200dp"
android:layout_height="200dp"
app:cardCornerRadius="12dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/beach_bg_placeholder" />
</androidx.cardview.widget.CardView>
I am developing my first Android app. Although I have 15 years of Java software development experience, Android is new to me. My desired look is a background image with other images on top of it, as well as labels and phone numbers. It seems like the best way to accomplish this is a Linear Layout for the background image, with a nested layout for the other fields on top of that. I have searched online and cannot find any sample code on how to accomplish this. Any recommendations would be greatly appreciated. Thanks in advance.
What are you using to develop? If you are you using Eclipse with the Android SDK this is super easy. Put the desired picture in the appropriate drawable folder, go to the graphical view of layout that corresponds to your activity, on the right side of the screen there is a list of all the properties, find background, then select your picture from drawables. You can also do this from the xml using android:background="#drawable/yourPic". This way you don't have to worry about having things layered on top of it.
I think you should go through followings:
1. http://phandroid.com/2011/05/11/10-tips-for-android-ui-design/
2. http://mobile.tutsplus.com/series/android-user-interface-design/
3. http://coding.smashingmagazine.com/2011/06/30/designing-for-android/
4. http://android-developers.blogspot.in/2011/09/thinking-like-web-designer.html
If I got, something like this can work:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<stuff>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<stuff>
</RelativeLayout>
<stuff>
</RelativeLayout>
I used it in an app, and made the trick.
First of all, RelativeLayout is the best layout to use. It depends on your design.
If your design says to keep all the views either vertically OR horizontally, you can use LinearLayouts in between.
My suggested way:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout android:id="#+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:orientation="Horizontal">
<View1 />
<View2 />
</LinearLayout>
</LinearLayout android:id="#+id/layout2"
android:layout_width="match_parent"
android:layout_height="wrap_parent"
android:orientation="Vertical"
android:layout_below="#id/layout1">
<View3 />
<View4 />
</LinearLayout>
</RelativeLayout>
Which will yield you something like this
I have a background in iPhone development, which may be a cause of some of my confusion with Android, which I am very new at developing.
My question is this: How to I create two TextViews, and specify their exact location on screen? For example, on the iPhone, I would create a UILabel, generate a rectangular frame that specified the label's size and position, and then set this rectangle to the frame property of the UILabel.
If you can help me understand the similarities with Objective C and iOS' UILabel, that would be most helpful.
On Android, we don't use absolute screen positions. This is highly discouraged. It's pretty understandable that you think this way if you are coming from iOS. But you need to revise your habits.
Instead of absolute positions, we use layouts, such as LinearLayout, RelativeLayout or FrameLayout. All of these allow you to arrange your views dynamically. And in many cases, it will automagically adapt to the screen size, which vary a lot from device to device.
Actually, there's nothing exotic about dynamic layouts. Many major UI toolkits, such as GTK, or Qt, work similarly. Pixel position are a bad idea in my opinion, except maybe in the Apple world, where the OS and the hardware are tightly coupled, but this is an exception actually.
So, in your case, all that you need is to put your text views into the appropriate layout. Please read the documentation and tutorials about the different types of layouts mentioned above to decide which one is best. The question is how you want your views to be placed relatively to each other.
Create a basic Android project in eclipse. You will be having a main.xml layout file in your project. You can open it in Eclipse using Ctrl+Shift+r and keying in main.xml
copy paste this in your xml after clearing its content.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:text="TextView One"
android:layout_height="fill_parent"
android:layout_weight="1"></TextView>
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:text="TextView Two"
android:layout_height="fill_parent"
android:layout_weight="1"></TextView>
</LinearLayout>
In my Android app, I have a tabbed Activity. In one of the tabs I have two TextViews and two EditTexts.
The first EditText is only one line, and that's fine. However, I want the other EditText, android:id="#+id/paste_code", to take up the remaining space, but no matter what I do to it, it will only show one line. I don't want to manually set the number of lines, since the number that would fit on the screen differs based on your device.
Here's the relevant code. It's nested inside all the necessary components for a tabbed Activity.
<ScrollView
android:id="#+id/basicTab"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Paste title"
android:layout_weight="0" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="#string/paste_title_hint"
android:id="#+id/paste_title"
android:lines="1"
android:gravity="top|left"
android:layout_weight="0" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Paste text"
android:layout_weight="0" />
<EditText
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:hint="#string/paste_hint"
android:id="#+id/paste_code"
android:gravity="top|left"
android:layout_weight="1" />
</LinearLayout>
</ScrollView>
Since the accepted answer doesn't address the situation fully, here's a proper fix for people coming to this while searching:
Firstly, Romain Guy from the Android dev team addresses this well in this blog post:
http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
Essentially, your ScrollView needs to contain the android:fillViewport="true" attribute.
If things aren't working once you've done that, here are a couple of things to check:
The layout inside the ScrollView (such as a LinearLayout) needs to have layout_height="wrap_content"
The view(s) you want to expand should have layout_height="wrap_content"
The view(s) you want to expand should have layout_weight="1.0" or similar
Don't forget to set minLines="3" or similar in the view(s) you want to expand if you don't want it/them to shrink too much.
The problem seems to come from your use of ScrollView. I've tested your code using a ScrollView as the parent container, and got the same problem. However if I replaced the ScrollView with a LinearLayout, then the second EditText properly expanded to fill the whole screen. The problem must be that ScrollViews are designed to wrap to their smallest possible size, regardless of what settings you put in android:layout_height. I experimented with another few layouts, e.g. a RelativeLayout using layout_above and layout_below, but those only affected its maximum size, not its size when empty. Unfortunately, that means I'm not sure how to solve your problem... Is there a way you can redesign your layout to use something other than the ScrollView as the parent container?