When to use CardViews vs tools:listitem when creating RecyclerViews? - android

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.

Related

Android constraint layout include another layout

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.

Multiple Views Vs Multiple Fragments

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

Android Studio: Can you display a view just for preview?

My app has a lot of views that are containers for fragments (which load an image and other views) and depend on an API to fetch images. To make the development of the design easier, I like to add a sample of that image in my xml. Right now, I'm adding a RelativeLayout with the FragmentContainer and a dummy ImageView using different visibility values for android:visibility and tools:visibility.
Is there a better way to show images just for preview purposes ? I'd like to have the preview Views not compiled in the release version.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:adjustViewBounds="true"
tools:src="#drawable/image"
tools:visibility="visible" />
<RelativeLayout
android:id="#+id/FragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
If I understood your problem correctly, you could do something like this:
instead of using dummy views, use
<include tools:layout="#layout/layout_preview" layout="#layout/layout_actual"/>
where layout_preview.xml is whatever you want to use only in the preview, and layout_actual.xml is what will be used in the app
in case you wanted to only add a view in the preview, but have no view at all in the app, you can use a layout_actual.xml with an empty merge tag
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"/>
if you don't want to include useless layout, you might want to create the dummy ones only for debug build type, it will show an error in the layout because layout_dummy will be missing but since it's tools attribute you should be able to compile and run

How does <merge> tag work internally

I am trying to understand how does <merge> tag internally work. I have studied some examples using View Hierarchy tool. So I understand basic using and how does it work on higher level, but I wanna to study more about this tag and inflating views in general.
So let's consider some simple layouts
activity_main.xml
<?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"
android:background="#drawable/bg"
android:gravity="center_horizontal">
<include layout="#layout/titlebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/some_text"
android:text="#string/hello"
android:padding="10dp" />
</RelativeLayout>
And of course titlebar.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/chrome" />
</merge>
In this case we have following result.
Let's change our titlebar.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/some_text"
android:src="#drawable/chrome" />
The result is really forthcoming.
Let's do more changes in our activity_main.xml 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="match_parent"
android:background="#drawable/bg"
android:gravity="center_horizontal">
<include layout="#layout/titlebar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/bug"
android:text="#string/hello"
android:padding="10dp" />
</LinearLayout>
And in titlebar.xml I left everything the same.
So in this case we have some weird things
1. Now our root layout is LinearLayout. We have specified nonexistent attribute android:layout_below="#+id/some_text" in titlebar file
In the same line we have another issue #+id/some_text doesn't exist anymore, now we have #+id/bug.
Let's look at the result
Here I have some questions :
We are can use any attribute (for any layout) in merged file,but if the viewgroup(layout) where this part is included (in our case activity_main.xml) doesn't have such attributes, what how this situation is solved, just ignored as we can see in result ?
We have hardcoded id of view above imageview,it works if id is exists, but if it doesn't , as we can see in result it is also just being ignored
So I have already written a lot.
To sum up, where works of XML parser exactly with merged and include tags is described, also it will be good to know where sources of XML parser is located, to look through it.
I will be grateful for everyone who read this line and can suggest something or give advice.
Thx in advance.
If an <include> tag includes both layout_width and layout_height, it will override all of the root view's (of the file it is including) layout parameters.
A merge is a way to avoid an additional depth in the view hierarchy - an XML layout file must only have 1 root - so it must either have a single View, a ViewGroup which can include additional Views or a <merge>. When you're including a layout with multiple Views inside a ViewGroup, you may be adding extra unneeded complexity to your hierarchy - for example, 2 vertically orientated LinearLayouts may not be required. The merge allows you to remove the extra ViewGroup, and merge its Views into the ViewGroup where it is included.
Including a layout with a merge with a single View is the same as just including a layout with the single View directly, except that with the merge there isn't a 'root view' of the layout, so the include will not override its layout parameters (I believe).
When a View or ViewGroup is inflated into a ViewGroup which doesn't support the layout parameters that the child specifies, the parameters are just dropped. This occurs when including or inflating (using a layout inflater).
If a child View or ViewGroup is added to a ViewGroup (using addView), it is possible that the child already has layout parameters assigned, and if they aren't compatible with the ViewGroup it is being added to, it may result in a class cast exception later on during measuring / layout.
Your second question is to do with RelativeLayouts layout rules, and its behaviour can be defined using android:layout_alignWithParentIfMissing

What are the different ways to design layouts in android?

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.

Categories

Resources