Is it possible to show a preview layout for ViewPager in AndroidStudio like in ListView/RecyclerView/etc.?
Short answer: No.
I think you're talking about ViewPager from ViewPager 2. My answer will be assuming ViewPager 2. Pls update the question to clarify that.
- Workaround: a hidden include
<include
android:visibility="gone"
tools:visibility="visible"
layout="#layout/item_that_shows_inside_viewholder"/>
And I agree that's a very poor way to do it.
If in constraint layout you can loosely match the same constraints to make this show on top. And yes, you will inflate this in production code so you may incurr in performance slow down depending on what you have there.
It's very unfortunate that tools:layout doesn't exist or work properly (yes, I got inconsistent results while trying it).
- 2nd less worst way is using isInEditMode on code on the parent class
something in the fashion of
class CustomView ....
init {
// inflate layout that contains ViewPager
if ( isInEditMode() ) {
//do something that replaces ViewPager with its inflated view holder
}
}
which has served me well when I can use that. However that's unsuitable for most places.
- If at least ViewPager were not final we could extend and do some tricks there using isInEditMode like above.
- You can make a custom class wrapper with internal field ViewPager
One way that does certainly work is making your custom class extend FrameLayout and having an internal view that is your actual ViewPager. But then you have to re-implement and delegate all its methods, which is a big pain. Maybe kotlin has a way to do that, but so far I don't know how. Or maybe using reflection or kotlin poet could be a way to do that. It's too risky for my taste.
- If we could make a databinding adapter to do the isInEditMode like above it would work. But databinding adapters don't run in preview.
- I tend to think these tools attributes get processed by Android Studio, so it would take probably an android studio plugin to work around it.
This is the current full list of tools attributes: https://developer.android.com/studio/write/tool-attributes.html#toolslistitem_toolslistheader_toolslistfooter
It may be useful reading this Android XML Is there a way to use the tool namespace with custom attributes?
where a library to read custom attributes with tools gets mentioned. There may be an alternative with this library, but I have never used it and not sure how it works:
https://github.com/giljulio/sneakpeek
I'd love to be proved wrong, but in my opinion all of the options are dead ends or too much effort.
In Andriod studio some views are shown in run time but not in compile time. Think about Frame Layout as a container for fragment transaction. We may place any kind of views on that container in run time. So, it's not possible to show a view while coding. The viewpager is playing same kind of role here. So, we can't show a view there before running and actually placing a fragment/other view there.
I hope you are clear now. :)
This is possible, when putting the ViewPager into it's own XML layout resource.
Alike this one can show the desired Fragment instead of the ViewPager:
<fragment
android:id="#+id/fragment_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="#layout/fragment_viewpager"
tools:layout="#layout/fragment_preview" />
This also provides the XML preview for the navigation graph design view.
tools:layout only works with fragment, but not with include.
i think it's not...some of the layouts have no preview while coding or designing ...like TabLayout
Although I don't think there is such a functionality out of the box, I used the following workaround to achieve design time preview for the ViewPager:
Add an <include> with the view that you will use in your ViewPager as a layout,just after the ViewPager itself
Set tools:visibility="visible" and android:visibility="gone" to this <include> view so that it will be visible at design time but not at runtime. Also set tools:visibility="gone" to the ViewPager so that it will be invisible at design time.
The idea is to hide ViewPager at design time and show its contents instead while doing the opposite at runtime. This should work for other controls as well.
To show an example:
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/tabl1"
tools:visibility="gone">
</androidx.viewpager.widget.ViewPager>
<include
layout="#layout/fragment_example1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"
app:layout_constraintTop_toBottomOf="#id/tabl1" />
I hope this helps you
Related
There are 100+ layouts in a resource folder on android, I can go through them one by one and look at the preview in android studio. They all utilise code like:
tools:text="text for preview"
tools:visibility="visible"
Is there a way to inflate all those one after another in a list/linear layout? And upgrade the tools:xyz attribute to be shown as the real android:xyz attribute in this view
Context&Purpose: To show them in the app under a debug menu dedicated specifically to show available layouts. This is to communicate with both other developers and people without android studio.
I want to avoid doing it manually as it needs to be maintained and that can end very badly for debug functionality such as this. (And that it is a lot of layouts does not help either of course)
After writing it down it feels unlikely, but maybe someone out there have a nice angle on this?
Depending on the complexity of each layout, inflating a hundred of them at once could be quite taxing. You may run out of memory, or get a fair bit of jank. If you are OK with this, then I would say try using the include tag in your debug screen layout
A simple/naive implementation would be something like
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/A"/>
<include layout="#layout/B"/>
<include layout="#layout/C"/>
<include layout="#layout/D"/>
...
</LinearLayout>
I probably wouldn't recommend doing this, but it might get the job done.
As far as the second part of your question, using tools values as actual values, I don't think there is a way to accomplish this. In fact the tools values are not even available during run time as they are stripped out during the build process.
When I developed, I found a new widget called android.support.v7.widget.ButtonBarLayout unexpectedly. I tried to search it on the internet, but nothing was found, even on the official development documents site.
In the meantime, I found two ButtonBarLayout when I search ButtonBarLayout everywhere in Android Studio, one is android.support.v7.widget.ButtonBarLayout and the other is com.android.internal.widget.ButtonBarLayout. I tried to read source codes of both, I found that they are the same except package name. So I thought maybe android.support.v7.widget.ButtonBarLayout came from com.android.internal.widget.ButtonBarLayout after the internal ButtonBarLayout was through tests and released. At the same time, ButtonBarLayout is inherited from LinearLayout.
But there are some question:
What can we get from ButtonBarLayout literally and how should we use it?
I noticed the variable of private boolean mAllowStacking. When it changes, orientation of this layout would be changed. But I didn't really understand what it is used for.
So does somebody know ButtonBarLayout well?
P.S.: I used Android Studio of 2.0.0 Preview 4 and Gradle Plugin of 2.0.0-alpha3 and Android Support Library of 23.1.1 and Platform-tools of 23.1 and Build-tools of 23.0.2.
As others pointed out, the class description tells exactly what it is: an extension of LinearLayout that automatically switches to vertical orientation when it can't fit its child views horizontally.
I might add that this was clearly done to fit with the material design specifications about dialogs. They make a distinction between side by side buttons and stacked buttons. See for example:
Side-by-side buttons are recommended when the text of each label does
not exceed the maximum button width, such as the commonly used
OK/Cancel buttons.
While you should go for stacked buttons when the single button is too large, or there's not enough room for both:
When text labels exceed the maximum button width, use stacked buttons
to accommodate the text. Affirmative actions are stacked above
dismissive actions.
So, one possible use of this class, is when designing your own dialogs. For example, AlertDialog and AlertDialog.Builder offer internal support for dialogs with buttons, but sometimes you just want to subclass DialogFragment or AppCompatDialogFragment for a better control.
There, it might be useful to setup a bottom button bar that follows the design guidelines, and have full control on the buttons (like enabling and disabling, things you can't do with an AlertDialog AFAIK).
The source code describes ButtonBarLayout as follows:
/**
* An extension of LinearLayout that automatically switches to vertical
* orientation when it can't fit its child views horizontally.
*/
So, in essence, it is nothing but a smart LinearLayout which manages auto-switching orientations based on available space on screen.
The same ButtonBarLayout.java file describes mAllowStacking in comments as follows:
/** Whether the current configuration allows stacking. */
Source Code Here
You are right first of all. ButtonBar layout does not seem to be featured anywhere in the official Android documentation. I tried myself to search about it, but to no avail. However I have found some information which defines what is a ButtonBar layout and when to use it. Hopefully this will help you.
Most tutorials use the Buttonbar layout in a dialogbox or at the bottom of a screen to confirm or decline an option. The image below is a visual representation of how the ButtonBar layout has been used in a screen.
The screenshot above has the following layout xml:
<LinearLayout
style="?android:attr/buttonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/Button01"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Show" />
<Button
android:id="#+id/Button02"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Change" />
</LinearLayout>
<EditText
android:id="#+id/myView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
So essentially what Android is doing here is simply creating two buttons next to each other in a LinearLayout with each button having the match_parent parameter set to the width. Hence each button takes half the size of the screen. Android have actually taken away the hassle of creating seperate buttons and positioning them correctly to fit different screens, by creating a simple widget handling this altogether.
As with the support library, Android have implemented this for developers using an earlier API. It is normal for them to use the support library for this purpose.
Hope this helps :)
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/com/android/internal/widget/ButtonBarLayout.java
Looking into the code, I think it's a LinearLayout for buttons (duh). You can probably look at it like the Dialog buttons divided by a vertical spacer: | . AllowStacking will change the orientation to vertical and the gravity to the right instead of bottom. I should try it out to give a better answer
ButtonBarlayout is not featured anywhere in the official Android documentation.
it is used for auto-switching orientations according to the space.
Regarding your question:
How should we use it?
I guess it is undocumented because it is not stable yet.
It just popped up because this long lasting complaint originate from poor ROM modification by device vendor.
https://code.google.com/p/android/issues/detail?id=78377
See #270 for the resolution regarding classpath and why all classes inside .internal. were made public.
And nope even that fix a lot of bugs from poor ROM modification are still out there (in lots of device of well known brands). The issue is soon declined by project member.
I don't think we should use it just yet until the document show up.
Just my $.02 though.
Just to add to the other answers, if you guys want to check the orientation of a ButtonBarLayout you should check the orienation AFTER the value has called on measure.
In other words (Kotlin):
buttonBarLayout.post {
val orientation = buttonBarLayout.orientation
val height = buttonBarLayout.measuredHeight
}
I'm no Android expert but I am aware of discussions regarding the appropriate use of LinearLayout and RelativeLayout, keeping the view hierarchy as small as possible, avoid unnecessary passes of onMeasure(), etc.
Lets imagine I have two ImageView's that I want to position completely INDEPENDENTLY, the first in the center of the parent and the second in the bottom left of the parent. (note this is a vastly simplified example of far more complex real life requirements).
The obvious way to solve this is using a RelativeLayout...
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="true"
android:layout_alignBottom="true"
android:src="#drawable/second_image" />
</RelativeLayout>
However something keeps telling me that a RelativeLayout isn't appropriate in this situation because I don't want to organise the children relative to each other. All I want to do is position the children according to the parent and I wonder if using a RelativeLayout causes some unnecessary layout calculations that I don't really require.
I am wondering if there is another ViewGroup type that would perform better? Its totally possible to achieve what I want with a FrameLayout for example but I've no idea if this is more performant or if I am abusing the intent of a FrameLayout etc...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="#drawable/first_image" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/second_image" />
</FrameLayout>
Maybe there is another Layout type I am unaware of?
Short answer
Given the information you have provided, the FrameLayout has a good chance of performing better. As you may have learned already watching (Adam Powell quote in Google I/O 2013 conference),
[...] RelativeLayouts will measure child views more than once in order to solve some of the constraints you give it. So, being generic has a cost [...]
From what I read and understood, this is not guaranteed and it depends on the constraints you give it.
Long answer
It really depends.
We all read Romain Guy blog post : Android Layout Tricks #1, who said that most people misinterpret his post and started using RelativeLayout everywhere.
This post, if you haven't read it, talks about how removing one hierarchy level using a RelativeLayout instead of a LinearLayout which saves loading time in a list.
Basically, it means that if you don't need them, as you described it yourself
[...] I have two ImageViews that I want to position completely INDEPENDENTLY [...] I don't want to organize the children relative to each other
you should not use them because of that reason.
Concrete example of : "Don't use them if you don't need to."
For instance, in one of our applications, we have serious performance issues on devices running Gingerbread -- which we want to support.
Our most complex layout involves a vertical ScrollView, attached to the current activity, in which we have several containers and one HorizontalScrollView that displays images and information which are contained in a complex LinearLayout.
We started to replace the LinearLayout by RelativeLayout. The result: no obvious improvement -- equivalent or maybe worse.
Since that layout is fairly complex, adding more RelativeLayouts embedded in each other just increased the onMeasure() calls that were made for a single draw.
Even a small circular ProgressBar was now spamming the UI thread with several measure calls because it was in one of those embedded RelativeLayout which triggered recalculations of the whole view.
I`m wondering about one thing. If I decide to have a part of my View same in every Intent. For example 2 buttons at the bottom of screen and for example I have 3 diffrent views, List, Detail and a third one :) Do I need to put the buttons on every xml schem for each view or can I create other xml and attach it in each activity with all listener etc.
If I can attach in activity how can I do that ?
Create a XML buttons.xml with the common elements
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageButton
android:id="#+id/myButton"
android:src="#drawable/ic_title_search"
android:onClick="myHandle" />
<ImageButton
android:id="#+id/myButton2"
android:src="#drawable/ic_title_search"
android:onClick="myHandle" />
</merge>
Include it in another xml:
<include layout="#layout/buttons"/>
where buttons is the name of the xml file to be included
You can use the <include /> tag in your XML files.
See Layout Tricks for an example.
Create a separate layout for your buttons then in the layout you wish to display them use the include tag.
This will allow you to reuse the same layout in multiple parent layouts.
The include works as stated above you could also consider using fragments
Fragments
You can use these in older versions of Android by including the compatibility library in your application. It's definitely more work than a simple include but if you need some reusable UI for more sophisticated features than simple buttons you might want to look at that as well
How to use compatibility API
When I run my application, buttons are not displaying(A little part is displaying, that makes feel that something is there), although I scroll down.
How to solve my problem. Is there any way to set size of textboxes (Where size depends on screen size).
Pankaj did you checked the orientation of the root LinearLayout tag ??
All you need to do is change root LinearLayout's orientation to vertical & you will see every button in your layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
& please read more about layouts before implementing them.
As #100rabh already said you should really start reading about Android layouts.
Some very good articles by Romain Guy are here and of course on his blog.
There is also a very good series of articles on Mobiletuts+ called Android User Interface Design by Lauren Darcey and Shane Conder.
You should really check that out and then redesign your layout.
As you're using linear layouts, you can use android:layout_weight. If you search, you'll find many examples.