I am having more of a conceptual question when it comes to ConstraintLayout. I want to re-use a layout inside my ConstraintLayout. But I ask myself a question that the ConstraintLayout aims at avoiding nesting of layouts and including a layout will decrease the ConstraintLayout performance. What is the best/ good practice to avoid nesting of layouts and at the same time re-use a layout so as to avoid code duplication?
You can use <merge/> tag to eliminate redundant view groups in your view hierarchy when including one layout within another.
Example:
main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<include layout="#layout/include_layout"/>
</androidx.constraintlayout.widget.ConstraintLayout>
include_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="33dp"
android:text="Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button" />
</merge>
Result:
In this case, without the <merge/> tag, you'll have two ConstraintLayout in the layout hierarchy.
Reference: https://developer.android.com/training/improving-layouts/reusing-layouts
Bottom Line
Don't be afraid of nesting ConstraintLayout as long as your View hierarchy doesn't grow too deep (<10). I'd consider it good practice to reuse and nest your layouts to avoid code duplication whenever it makes sense.
Background
I quote from the Android Developers page:
Additionally, if your app targets Android 7.0 (API level 24), it is likely that you can use a special layout editor to create a ConstraintLayout object instead of RelativeLayout. Doing so allows you to avoid many of the issues this section describes. The ConstraintLayout class offers similar layout control, but with much-improved performance. This class uses its own constraint-solving system to resolve relationships between views in a very different way from standard layouts.
Optimizing Layout Hierarchies from the developers page mentions that
Deep layouts - Layouts with too much nesting are bad for performance. Consider using flatter layouts such as RelativeLayout or GridLayout to improve performance. The default maximum depth is 10
However, ConstraintLayout is not mentioned on this page explicitly and I might add that a depth of 10 nested layouts would almost surely result in a rather cluttered UI.
To add, in my professional experience as a software developer, I've never had performance issues with ConstraintLayout despite the fact that my team does use nested ConstraintLayouts regularly (with limited depth, I might add), most of the time encapsulated in custom View Components. That being sad, these events certainly don't occur excessively, since ConstraintLayout enables one to build UIs without excessive use of nesting.
Related
I'm going to create a complex/normal design that has an empty screen layout & shimmer layout.
my question is to have all in one layout with multiple <include> files is better than doing two fragments and keep replacing them.
more details:
1- make the data screen shown & empty screen hidden as follows:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/common_toolbar" />
<include layout="#layout/empty_layout"/>
// my data layout
</LinearLayout>
2- create a FrameLayout and keep change the container for different screens with multiple fragments:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
I need to know the best practice as depending on slow rendering of multiple views.
another question, is that included in for shown/hidden views or it depends on shown ones only as I got confused
and need to apply best practices.
if you attend to reuse some views Fragment is the best, otherwise, if you looking best to render I advise you to use constraint layout and section your views with a group so you can hide and show group
take a look to this one How to group multiple views in a ConstraintLayout
I'd like to create a Layout like this.
What is the best way to perform this?
There are several ways to do it, first and common step is define border around parent layout and define margin for child layouts. after that in second step you can use one of the following to achieve this.
you can use Linearayouts with orientation vertical and then by using weightsum and weights you can achieve this.
another approach is by using Relative. in relative layout you can provide other views position relating to other layout component position.
third approach is by using Constraint layouts, provide constraints and you will achieve this.
You can use this code to make that design:
<?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:weightSum="2"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#android:color/black"
android:layout_weight="0.4"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.6"></RelativeLayout>
</LinearLayout>
You can change values of layout_weight to change the rate.
Some of the ways to achieve this layout and a few a performance cautions with these are stated below:-
1.With a linear layouts using the weights parameters will cause a performance hit, as the it would cause the views to be measured twice before being layout.And we has a deeper heirarchy with linear layouts which again causes slow rendering.
With relative layouts , even though we get a flat heirarachy but the views are measured twice before drawn, again a nested relative layout (relative layout with in another relative layout) will cause the rendering time to increase as now, the view would be measured 4 times.
3.It would be better to use constraint layout to get the better performance with flater view heirarachy.
4.You might also want to consider using fragments if the inner layout has a menu structure causing changes in first child , with frame layout as the root parent.
A few links to understand about the performance benefits:-
Android Layout Tricks #1
Understanding the performance benefits of ConstraintLayout
I came across this code:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/darker_gray"
tools:listitem="#layout/recyclerview_item" />
where tools:listitem was a layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textView"
style="#style/word_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/holo_orange_light" />
</LinearLayout>
My question is, when creating recyclerviews, when should we choose Cardviews as its items and when should we choose layouts such as the one mentioned above?
What are the advantages one provides over the other or are they the same(Note that the recyclerview_item layout XML doesn't have any Cardview tags, so they aren't atleast literally the same)?
tools:listitem only sets a design-time preview for a list item by providing a specific layout resource, be it a CardView-based layout or something different.
You can use tools:listitem along with other tools attributes and #tools/sample resources to emulate components' runtime or compile-time behaviors such as layouts, dummy data, visibility e.t.c.
Those attributes do not affect your app's runtime behavior in any way.
Additionally, you can read this tutorial on tools attributes.
As for cards vs regular layouts, there are some in using cards as containers: cards support elevation, shadows, rounded corners and have a consistent visual style while supporting different content lengths with no additional actions required e.t.c
Personally, I'd use a CardView-based layouts in cases where I need to show some list items with straightforward layouts in a platform-consistent way.
From my vague understanding of layout managers I think that nesting layouts inside layouts can be inefficient (is this true for android too?)
I am trying to do this layout but have having to next layouts. Is there a better layout manager I could use so that things are not nested? All of the components are currently fragments so it is a case of laying out the fragments rather than the individual components.
Thanks
I don't believe there is a way to get that look without nested layouts. If so, it's because you're doing a lot of graphics that probably isn't necessary (not knowing your other requirements). And by "a lot of graphics" I mean from your image, if you want dynamic content in each box, then you must use nested layouts unless you have one layout and then re-draw the cent portion of the screen to give the effect of nested layouts.
Unless you have a performance problem, you don't need to worry about the efficiency with a low number of layouts (i.e. less than 100 or so). I have several apps with several layers of nested layouts (up to 10 layers of nesting) and no measurable difference in performance.
If you have a ScrollView or ListView with hundreds of children, then you might be concerned with nested layouts. I have worked with a few of these, and it can make a difference. For example, I had a ListView with 5,000 or so items, each had about 5 layouts. When I dropped it to 3, I noticed a difference on the backend. Neither were noticeable to the user. (And no, I could not recycle the view containers efficiently since each item essentially needed it's own layout - partial recycling was possible.)
Though it's a bit complex to set up, you can use GridLayout to achieve that. Assuming the top and bottom views have a fixed height, that would be something like:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:useDefaultMargins="true">
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="120dp"
android:layout_row="0"
android:layout_column="0"
android:layout_columnSpan="2"
android:background="#ffff070c"
android:layout_gravity="top"></FrameLayout>
<FrameLayout
android:layout_width="200dp"
android:layout_row="1"
android:layout_column="0"
android:background="#ff12ff1a"
android:layout_rowSpan="2"
android:layout_gravity="fill_vertical"></FrameLayout>
<FrameLayout
android:layout_height="64dp"
android:layout_row="1"
android:layout_column="1"
android:background="#ff0906ff"
android:layout_gravity="fill_horizontal"></FrameLayout>
<FrameLayout
android:layout_row="2"
android:layout_column="1"
android:background="#ff737373"
android:layout_gravity="fill"></FrameLayout>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_row="3"
android:layout_column="0"
android:layout_columnSpan="2"
android:background="#ffbebebe"></FrameLayout>
</GridLayout>
which produces this:
I'm fairly new to Android development. I'm wondering what are the different ways that are used to design XML layouts. Ive been using the eclipse drag and drop interface and I've seen http://droiddraw.org/ while doing some searching. Just wondering if there are any other possibly better ways out there to design layouts that professions use because I'm having a hard time with the eclipse interface making complex designs?
First of all check out the android developer site user interface page
http://developer.android.com/guide/topics/ui/index.html
There are basically three different ways you can make an android layout:
XML
http://developer.android.com/guide/topics/ui/declaring-layout.html
You can define a static layout using XML. Perhaps a good way to think of it is a sort of shorthand. It is very easy to declare Views and attributes, and the hierarchical format of XML makes it a bit easier to visualize.
This is a typical layout
<?xml version="1.0" encoding="utf-8"?>
<ViewGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:attribute="value" >
<ViewGroup android:attribute="value" >
<View android:attribute="value" />
</ViewGroup>
<View android:attribute="value" />
</ViewGroup>
Then you use setContentView(R.layout.layout) in your activity and go about your business.
Java
You can do everything you would do in XML, plus add things like listeners, or do other dynamic things that you cannot in XML. Here is how you might declare a typical layout (ViewGroup is abstract so you would have to use a subclass. The same goes for XML)
ViewGroup parent = new ViewGroup(this);
ViewGroup vg1 = new ViewGroup(this);
View v1 = new View(this);
View v2 = new View(this);
parent.addView(vg1);
vg1.addView(v1);
parent.addView(v2);
v1.setOnAwesomeListener(new AwesomeListener() {
onAwesome(View v) {
doDynamicThings();
}
}
setContentView(parent);
Hybrid
This is the case used most often in my opinion. Declare a layout in XML with an id, like android:id="#+id/v1" then load Views from XML into Java
setContentView(R.layout.layout);
View v1 = findViewById(R.id.v1);
// dynamically change v1
How to design a layout using XML
So the lack of GUI designer tools has left you no choice but to dive into coding up your layout by hand. Good news is that once you get the hang of it you should be able to tackle any layout you wish. Let's look at the building blocks
ViewGroup
First off you need to choose a ViewGroup to define the structure of the layout, or section of the layout. Remember that these can be nested, so design top-down and try to classify sections of the layout based on the form you want them to have. There are two main options:
LinearLayout
As the name implies, useful for arranging items in a line. Choose an orientation, horizontal or vertical, and simply add items. They will be added in top to bottom or left to right ordering.
RelativeLayout
Useful for placing an item in a specific location on the screen. So if you want to put a button in the top-left, or a bar across the top, this is your ViewGroup.
Layout Parameters
Used for defining the width, height, weight, and other aspects of a view.
There are two options for width and height: fill_parent (replaced with match_parent in API level 8) and wrap_content. The view can choose to either fill the parent view's width, or take only the space it needs.
There is another useful layout parameter, unique to LinearLayout, called weight. It is useful for letting views share space in ratios, or letting one view take the space left over after other views in the LinearLayout take their share.
Example
Let's try to design the layout for Google Maps. Pretend it is a layout that I have in my head, and I want to implement it. Here is a screenshot
I will try to break this down:
Looking at it, there is a bar across the top and a map underneath it. I believe this could be implemented with either a LinearLayout or a RelativeLayout. However, the buttons in the bottom right and left scream RelativeLayout, so I will go with that.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TODO:BAR
android:id="#+id/bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
</TODO:BAR>
<MapView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/bar" />
<ImageButton
android:id="#+id/latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical" >
<ImageButton
android:id="#+id/zoom_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
android:id="#+id/zoom_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
Now some explanation. In RelativeLayout you use alignParent[direction] to specify where the view goes. I also wanted some space on the sides, so I used margin[direction] to specify in dp or density-independent pixels. As you can see, wrap_content is used most of the time, so the buttons would acquire the size of the image used on them.
Now everything is defined but the bar at the top. I'm going to break it up into four different Views: The dropdown menu view, the search view, the layers button and the my location button. The way I would like it to work is put the menu at the far left, and the layers and my location buttons on the right, with the search box taking up the remaining space. This sounds like a job for LinearLayout and weight! Here is how I define the bar, which can be inserted into the placeholder above to get the final layout
<LinearLayout
android:id="#+id/bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" >
<ImageButton
android:id="#+id/dropdown_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="#+id/search"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:id="#+id/layers"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageButton
android:id="#+id/my_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Setting the width of the search bar to 0dp means let the other views take what they need, then the weight says take the remaining space.
And there you have it. A recreation of the basic layout for the Google Maps app (minus button images and other niceties like custom views), showing how you might use various layouts and XML fairly painlessly. Hopefully this was useful.
The tool chain is a little weak in this area. I don't really care for DroidDraw, and the Eclipse GUI editor is not very good for anything more than simple layouts. It often renders RelativeLayouts incorrectly for example.
Personally I do almost everything directly in XML. You have to understand how all the different Layout classes work to do anything complex anyway. The only real downside to XML is that all of the extra cruft from tags, attributes, etc. makes for a lot of extra stuff to type, but the editor takes care of most of that for you.