Custom wrapping view in Android using xml layouts - java

I want to create a wrapper element that can be reusable throughout the whole app, because it's the base of each screen.
This wrapper should be possible to add to layout editor in Android Studio and needs to be able to hold any inner elements inserted in editor.
But these elements have to be inserted inside the layout under header with image and only inside a specified area defined in wrapper xml layout (innerContainer).
This is the layout of wrapper:
<ScrollView
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.support.constraint.ConstraintLayout
...
android:background="#drawable/frame_container_layout"
tools:context=...>
<include
android:id="#+id/cv_header"
layout="#layout/cv_header"
...>
</include>
<android.support.constraint.ConstraintLayout
android:id="#+id/innerContainer"
.../>
</android.support.constraint.ConstraintLayout>
What I need is to use this layout in custom view in a way, that when it's used somewhere, the elements will be only inserted into innerContainer.
Child XML:
<...custom_views.WrapperFragmentView
...
app:exampleColor="#33b5e5"
app:exampleDimension="24sp"
app:exampleDrawable="#android:drawable/ic_menu_add"
app:exampleString="Hello, WrapperFragmentView">
<TextView
android:id="#+id/textView1"
...
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</...custom_views.WrapperFragmentView>
The child is now inserted over the wrapper layout, which is what I don't want. It's not inside innerContainer.
In kotlin file I defined
class WrapperFragmentView : android.support.constraint.ConstraintLayout {
...
private fun init(attrs: AttributeSet?, defStyle: Int) {
var inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(R.layout.cv_wrapper_fragment, this, true)
findViewById<android.support.constraint.ConstraintLayout>(R.id.innerContainer)
The innerContainer is the view I want to have as a root element for the children that are going to use it. Not the whole layout cv_wrapper_fragment.
How to set this in the WrapperFragmentView?
Or, if the whole concept is wrong and if there is an easier approach how to work with reusable wrapping elements I am all for that.

Related

Android fragment preloading data

Hello I'm trying to make an application that has multiple bottomnaviagtion tabs.
Currently it works because fragment data (for example, images) are static. However, if I want to make them dynamic, I'll have to create a preloader.
So I want to display a loading layout (for example R.layout.loading) UNTIL (async) function has completed and obtained data from server. Then I want to replace the layout in the fragment with a new layout (R.layout.datafragment)
Fragment onCreateView:
return inflater.inflate(R.layout.loading, container, false);
In summary it should work exactly like youtube bottom tabs.
You should create in your activity layout a placeholder for those dynamic fragments and a loader which is by default gone, but when you start loading data from the server you should make it visible (loader). Then, when you load necessary data, just start fragment transition and place whatever fragment you have loaded.
Your parent activity's layout should be like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Navigation View and Fragment Container-->
</RelativeLayout>
<RelativeLayout
android:id="#+id/progress_layout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
</RelativeLayout>
Then you simply show/hide progressLayout based on your requirement. Thanks

Android Studio - How to programmatically add layout_below param to CardViews inside a PercentRelativeLayout

I am here because I am trying to set programmatically the layout_below parameter of some cardViews without success.
These cardViews are located inside a PercentRelativeLayout (I do not know if it is relevant but these cardviews have been added programmatically too).
I show you the code to make it clear.
...
<android.support.percent.PercentRelativeLayout
android:id="#+id/prl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv0"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv1"
// here I would like to add android:layout_below="#+id/cv0"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:percent="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/cv2"
// here I would like to add android:layout_below="#+id/cv1"
android:layout_width="match_parent"
percent:layout_heightPercent="65%"
percent:layout_marginTopPercent="2%"
percent:layout_marginLeftPercent="2%"
percent:layout_marginRightPercent="2%"
card_view:cardCornerRadius="2dp"
card_view:cardElevation="4dp">
</android.support.v7.widget.CardView>
</android.support.percent.PercentRelativeLayout>
...
I tried to do something like this in my Java code but without success.
PercentRelativeLayout prl = (PercentRelativeLayout) view.findViewById(R.id.prl);
CardView cv = (CardView) LayoutInflater.from(getActivity()).inflate(R.layout.cv_block, prl, false);
cv.setId(currentId++);
prl.addView(cv);
cv = (CardView) LayoutInflater.from(getActivity()).inflate(R.layout.cv_block, prl, false);
cv.setId(currentId++);
RelativeLayout.LayoutParams cv_lp = (RelativeLayout.LayoutParams) cv.getLayoutParams();
cv_lp.addRule(RelativeLayout.BELOW,currentId-2);
/* I have also tried to call cv.requestLayout() but nothing changed */
prl.addView(cv);
As you can see, I am trying to generate cardviews and insert them one below the other.
Thanks in advance for your help.
PercentRelativeLayout is depreciated, so you are encouraged to use other type of layout.
This class was deprecated in API level 26.1.0.
consider using ConstraintLayout and associated layouts instead. The following shows how to replicate the functionality of percentage layouts with a ConstraintLayout. The Guidelines are used to define each percentage break point, and then a Button view is stretched to fill the gap:
ConstraintLayout gives lots of opportunities.
More about PercentRelativeLayout deprecation here.
More about ConstraintLayout and how to use it here or video tutorial.

How to add a title to a fragment in Android

In AndroidStudio, I selected "New->Fragment->Fragment (List)" to create a list of items. It works fine and displays all the items; however, I would like to have a title at the top.
If I add another TextView to the "fragment_item_list.xml" file, then the title appears in all the items in the list. From other questions I figured that if I create another LinearLayout xml layout file (something like "list_header.xml") and put a TextView in it, I can use a layout inflater to inflate this layout in the fragment activity, e.g. in onCreateView,
View header = inflater.inflate(R.layout.list_header,container,false);
but then I don't know what to do with header to make it display somewhere in the fragment. I can add it to the original activity by calling container.addView(header); but how can I add it to the fragment?
I don't want to change the ActionBar title, firstly just for aesthetics, and secondly because the fragment covers it up. Ideally there would be a header like in an alert dialog.
Let me try to understand you. You want to add a title to your fragment list (like an header), not in the ActionBar. Right?
Looking the fragment_item_list.xml we have this: (I follow your steps: "New->Fragment->Fragment (List)")
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView 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/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:listitem="#layout/fragment_item" />
The RecyclerView is a container used for populate a list, in other words, the RecyclerView (or ListView) contain all the list only. So, you have to add another container (like LinearLayout, RelativeLayout, etc.) as root of the layout to add more views to the layout. Example using the LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/text_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World! I'm a header!"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/list"
android:name="com.veroapps.myapplication.ItemFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager"
tools:listitem="#layout/fragment_item" />
</LinearLayout>
With this you will have a list with a title at the top. Now, you can manage the title TextView in the ItemFragment(name of the fragment generated by Android Studio). And of course there are more ways to do that, but this is an easy one.
Hope this help you.
In your Fragment java class, there should be a method called onCreateView this is where you set the layout for your Fragment (and where the list is added). It will look something like this:
public static class ExampleFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.example_fragment, container, false);
}
}
In this Fragment the layout is inflated by this code inflater.inflate(R.layout.example_fragment, container, false); and this means there's is an xml file defining the layout called example_fragment.xml.
Your code will be the same, when you find this XML file. You can add other views inside it.
You will want to add another TextView above the RecyclerView or ListView already in that file.
Something like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
...
android:text="YOUR TITLE" />
<RecyclerView
... />
</LinearLayout>

Android View type at runtime

I'm creating an app which used a GridView to display a set of items. Each of these items is defined as follows:
<?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">
<com.example.myapp.customviews.Tile
android:layout_width="wrap_content"
android:layout_weight="1"
android:scaleType="fitCenter"
android:layout_height="match_parent"
android:id="#+id/tile" />
</LinearLayout>
In my OnItemClickHandler I want to check if the type of the View with id R.id.tile (My custom View class mentioned above) is com.example.myapp.customviews.EmptyTile. This class is a child of the Tile class.
Currently I'm checking if the class is an EmptyTile as follows:
LinearLayout tileLayout = (LinearLayout) gridView.getChildAt(position);
if (EmptyTile.class.isInstance(tileLayout.findViewById(R.id.tile))) {
Log.d("myappDebug", "Correct instance!");
}
I have tried checking using instanceof and tileLayout.findViewById(position).getClass() == EmptyTile.class but these also don't work. At runtime, my view is just a Tile View and not an EmptyTile View.
How can I check if my View is actually an instance of the EmptyTile class?
instanceof must work. But, in your XML, you define the view to be of type com.example.myapp.customviews.Tile, so why do you expect it to be an EmptyTile?
If you use EmptyTile (with the correct package of course) in the XML, the instanceof check and the other options will work.

How can I define a fragment's layout from XML?

I'm trying to define a fragment's layout in XML in the same way that I defined the layout of my view.
Is this possible? I tried several things, but none of them seem to work.
My activity layout looks as follows (main.xml):
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="full.lommeregner.Lommeregnerrv2Activity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lommeregnerv2">
</fragment>
</ListView>
Now, since I'm not a big fan of generating layouts through raw Java code, I tried defining my fragment as follows (fragment_lommeregner.xml):
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="full.lommeregner.Lommeregnerrv2Activity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lommeregnerv2">
<!-- my content was located here (some textviews, buttons and so on). -->
</fragment>
Am I doing something wrong? How can I define the layout of a fragment through XML?
A Fragment works much like an activity, in that you need a Java class file to go with it. you cannot create a Fragment just by creating a fragment layout - you need a class for your fragment:
Create a layout XML and an Activity subclass for your activity
Create a layout XML and a Fragment subclass for your fragment
Tie the two together in your Activity layout XML (or using FragmentTransaction if you want to do it in Java code)
If you haven't already done so, read, re-read and digest everything on this page:
https://developer.android.com/guide/components/fragments.html
There's a lot there, but Fragments are an essential part of Android apps now so it's required reading. The good news is that the basics of fragments is pretty simple.
Simply add into your <fragment> tag as property:
tools:layout="#layout/your_layout_xml"
And in your main.xml (or <fragment> tag container) into your parent container (in this case ListView):
xmlns:tools="http://schemas.android.com/tools"

Categories

Resources