I have an activity that presents a list and some icons. My activity design contains a ConstraintLayout at the top level with the list and the icons as children.
Now there can be a situation where we don't have any data. In that case I would like the activity to show neither list nor icons but instead show an image and some error text.
How would I go about implementing this in a way that I can still edit the layout in the Android Studio design view? In other words, not just add the image and the error text overlapping my normal activity elements and toggle their visibility programmatically. Are there layers or something? Or switchable fragments?
Or like this: How can I group view elements in a way that I can show and hide the whole group in the designer?
Yes, in android are Fragments (Android docs) and You can create two fragments, one for a situation when data is loaded successfully and second if data isn't loaded. You can start with the first fragment and when You get information about failed loading data You can switch fragments to second with information about fail.
But I think You can do this in one ConstraintLayout layout. In Your main layout add on top image as You would like to display it and set visibility parameter android:visibility="gone". Now You see everything and can create UI in design mode. And when You get information about failed with loading data just change image parameter to visible.
To do it programmatically:
ImageView imageView = findViewById(R.id.imageDataFailed);
imageView.setVisibility(View.VISIBLE);
How it looks with two containers:
<androidx.constraintlayout.widget.ConstraintLayout 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">
<!-- Here is container for success data load. When You failed load data set visibility="gone"-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button Success"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- Here is container for failed data load. If You want to change design just set `visible`-->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button Failed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I have been given the task to implement a feature on Mobile application. Previously I had no experience with Android nor Java.
What I need is one screen (one fragment) to display two lists of events with uneven number of members one after another, let's call them ListX and ListY.
I've made layout containing two RecyclerViews and two labels (one label to act as header for each of recycler views).
It is working as it is now and I have events displayed, but ListX is scrollable even though its layout_height is set to wrap_content (only 6 items displayed at the time) while ListY is not scrollable and is displaying all events in collection.
What I need is all items from ListX displayed in first RecyclerView (without scroll), and after that ListY displayed in second RecyclerView without scroll too.
Layout:
<FrameLayout
android:id="#+id/resultsView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/label_daily" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list_daily"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/label_daily"
tools:listitem="#layout/fragment_timetracking_event_item" />
<TextView
android:id="#+id/label_unfinished" />
<android.support.v7.widget.RecyclerView
android:id="#+id/list_unfinished"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/label_unfinished"
tools:listitem="#layout/fragment_timetracking_event_item" />
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
As you can see from XML both RecyclerViews have layout_height set to wrap_content yet first RecyclerView is not obeying.
Here is sketch of how it should look like
Is there any way to put both lists in one RecyclerView and make custom separators? Or any other way to anchor beginning of one list to the end of the other and make them show all items without scroll?
I hope to get help here.
You don't need 2 recyclerViews, you can achieve using single recylcerView.
You should read about getItemViewType & using same in bindViewHolder & createViewHolder
You can specify these three types
Header
DailyItem
FinishItem
Create your list like this
add Daily HEADER
add Daily ITEMS
add Unfinished HEADER
add Unfinished ITEMS
Now you can render both lists in single recyclerview
Your problem
...other way to anchor beginning of one list to the end of the other and make them show all items without scroll?
has a simple solution without rewriting your code to the one RecycleView - just put android.support.v4.widget.NestedScrollView instead of ScrollView in your xml layout. It seems to be a bug in the ScrollView widget, which is fixed in android.support.v4.widget.NestedScrollView.
P.S. After solving this problem you will face with other problem - Android RecycleView scrolls with no momentum, which is resolved in "RecyclerView within NestedScrollView Scrolling Issue". It is fine only for short item list in RecycleView because as it is mentioned in comments to above article
This is not a good solution since disabling nested scrolling will disable cell reuse as well, therefore loading all cells at once.
which will have impact on the memory consumption of your app in the case of long item list.
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
I want a content placeholder for my TextViews in a RecyclerView until the data is fetched & parsed from the server.
By content placeholder, I don't mean default text or a text saying no results. Please look how Facebook displays gray colored animated blocks before displaying the actual data on the web. I want to achieve that.
Basically a kind of loader unless my data is ready to be displayed (please don't suggest me with horizontal or spinning loaders).
e.g.: I display a gray colored block and as soon as my data is ready to be displayed I'll remove the block and then display the text.
All of that needs to be done in a RecyclerView. I hope I am clear with my need.
How do I achieve this?
I can't place dummy views in the RecyclerView because, unless I have the data my getCount will return 0 so no views will be displayed.
I don't want to display a dummy layout and then make it gone when I get the actual data, that doesn't look clean.
Without knowing exactly Facebook's implementation I assume they load an initial data source with "lean" data from which you can tell how many units you will need to display, based on that you could create a placeholder (that would be a type in your RecyclerView), once the full data for that placeholder was loaded you notify data set change and replace the placeholder with the full item (again another type in your RecyclerView).
Basically a kind of loader unless my data is ready to be displayed
If you have absolutely no data, for example you don't have the amount of "blocks" that will be displayed you can't display a placeholder as it might be discarded if you have an empty data set returned from your data source.
this should work,
<TextView android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="No Results" />
The id does the trick!
You have to be using a ListViewActivity for it to work!
If not extending ListViewActivity
try,
ListView.setEmptyView() read here
You need to create the skeleton layout and inflate it on the whole screen. Then you can use different libraries to add the shimmer effect.
drawable/skeleton.xml:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<solid android:color="#color/skeleton"/>
<corners android:radius="4dp"/>
</shape>
layout/skeleton_row_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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="#dimen/row_layout_height">
<View
android:id="#+id/icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_margin="15dp"
android:layout_gravity="center_vertical"
android:background="#drawable/skeleton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<View
android:id="#+id/topText"
android:layout_width="200dp"
app:layout_constraintTop_toTopOf="#id/icon"
app:layout_constraintStart_toEndOf="#id/icon"
android:layout_height="15dp"
android:layout_marginLeft="16dp"
android:background="#drawable/skeleton"/>
<View
android:id="#+id/bottomText"
android:layout_width="250dp"
android:layout_height="15dp"
app:layout_constraintTop_toBottomOf="#id/topText"
android:layout_marginTop="10dp"
app:layout_constraintStart_toEndOf="#id/icon"
android:layout_marginLeft="16dp"
android:background="#drawable/skeleton"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#drawable/skeleton"
app:layout_constraintTop_toBottomOf="#id/icon"
android:layout_marginTop="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>
In this tutorial I wrote you will find how to replace the skeleton with the recyclerView: https://medium.com/#sha17187/upgrade-progress-loading-with-a-skeleton-and-shimmer-effect-in-android-863ea4ff5b0b
I want to display two different activities in a single screen how can i do that in android?Please if anybody has idea share it.And I don't wanna use fragments.
I want to display a screen which contains some fields and below(at the bottom of the screen) I want another screen with some buttons.
Is this possible in android?
If so, How can i do this ?
You can't have two activities in one screen. You can have only one. So, ultimate solution is Fragments.
An activity is not directly a visual component, so I'm thinking that what you're really asking is how to have a single activity display different views.
There's nothing that says you can't rerun setContentView() with a different layout/view ID. But there's another non-fragments way of doing what your probably want.
You can define more than one full-size (match_parent) view in a layout. What you want to do is set the visibility for one of them to "visible" with android:visibility="visible" and all the others to "gone" with android:visibility="gone".
Then when you want to switch the displayed view, you'll run setVisibility(View.GONE) on the outgoing view and setVisibility(View.VISIBLE) on the incoming. It's important to use GONE and not INVISIBLE or the layouts won't render correctly.
Sample layout file:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<SurfaceView
android:id="#+id/video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
<WebView
android:id="#+id/web"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" />
</FrameLayout>
Sample Code to switch view:
video.setVisibility(View.VISIBLE);
img.setVisibility(View.GONE);
web.setVisibility(View.GONE);
That said, you probably want to learn how to use fragments since you can handle switching the view along with other state in a single unit of work (a transaction). But the above approach above does work for simple view changes.
We are developing an app that in one point, we need a screen like Honeycomb Gmail application :
http://www.cnx-software.com/wp-content/uploads/2011/02/android_3.0_honeycomb_gmail_app_fragments_700px.png
We are trying to use fragments and includes a listview to show our items.
We did exactly the same thing on this link : http://www.vogella.com/articles/Android/article.html#fragments_tutorial
But in any way we did not able to view different layouts,
what i mean is that, the only thing that we can show on the right fragment a single textview.
but we need a listview there, that we can view a thumbnail,some explanations and this needs to be clickable.
anyone to help?
Should work. I think you want to instantiate a ListFragment that, upon the user selecting a row, instantiates another ListFragment.
Maybe read this article aswell.
Below is an example for a layout xml file that has two fragments next to each other with an even width.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<fragment
class="package.of.fragmentA"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="#+id/fragmentA"
/>
<fragment
class="package.of.fragmentB"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:id="#+id/fragmentB"
/>
</LinearLayout>
In the case of the GMail application the class fragmentA would be a ListFragment and fragmentB would be a normal fragment class with a custom layout file.