handle empty data view in recyclerview - android

How to handle empty data View in a RecyclerView ,I have tried so many ways from internet but none seems to work. I am also using realm database so I don't know if this is the right way to check if it is empty or not.
this is my Fragment xml where the RecyclerView is located
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_no_data"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_dark"
android:gravity="center"
android:text="emptty"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#android:color/white"
android:visibility="invisible" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_favorite"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimaryDark">
</android.support.v7.widget.RecyclerView>
</FrameLayout>
and this is my fragment class
public class FavouriteFragment extends Fragment {
RecyclerView mRecyclerView;
FavouriteAdapter adapter;
Realm mRealm;
int positions;
TextView emptyText;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.favourite_fragment,container,false);
mRealm=Realm.getDefaultInstance();
RealmQuery<news> quotesRealmQuery = mRealm.where(News.class).equalTo("favourite",true);
RealmResults<News> mResults = newsRealmQuery.findAll();
emptyText= (TextView) view.findViewById(R.id.tv_no_data);
//adapter=new FavouriteAdapter(getActivity(),mResults,mRealm);
mRecyclerView= (RecyclerView) view.findViewById(R.id.rv_favorite);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
if (!mResults.isEmpty()) {
//if data is available, don't show the empty text
emptyText.setVisibility(View.INVISIBLE);
adapter=new FavouriteAdapter(getActivity(),mResults,mRealm,pos,single);
mRecyclerView.setAdapter(adapter);
mRealm.addChangeListener(new RealmChangeListener<Realm>() {
#Override
public void onChange(Realm element) {
adapter.notifyItemRemoved(positions);
}
});
} else
emptyText.setVisibility(View.VISIBLE);
return view;
}

Your RecyclerView is not transparent so you should remember to hide it when is empty:
if (!mResults.isEmpty()) {
//if data is available, don't show the empty text
emptyText.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
} else {
emptyText.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
}

Related

Materialio Appbar does not hide when scrolling down

I've followed the material documentation for top app bars and implemented a part of it in my app to be able to hide it, when scrolling down my list.
My Layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="#+id/ddd"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".pkgTestforend.DriverListFragment">
<com.example.dochjavatestimplementation.pkgTestforend.CustomLinearLayout
android:layout_width="match_parent"
android:id="#+id/cusLL"
android:layout_height="match_parent"
app:elevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/listAllDrivers"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
</com.example.dochjavatestimplementation.pkgTestforend.CustomLinearLayout>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true" >
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/topAppBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="PageTitle"
app:menu="#menu/top_app_bar"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:navigationIcon="#drawable/baseline_menu_24"
style="#style/Widget.MaterialComponents.Toolbar.Primary"
/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And the corresponding fragment:
public class DriverListFragment extends Fragment implements View.OnClickListener {
public DriverListFragment() {
}
public static DriverListFragment newInstance(String param1, String param2) {
return new DriverListFragment();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_driver_list, container, false);
setUpToolbar(view);
return view;
}
private void setUpToolbar(View view) {
Toolbar toolbar = view.findViewById(R.id.topAppBar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
menuInflater.inflate(R.menu.top_app_bar, menu);
super.onCreateOptionsMenu(menu, menuInflater);
}
ListView listViewDriver;
DriverListAdapter adapter;
RoomWithRxJavaViewModel viewModel;
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
listViewDriver = view.findViewById(R.id.listAllDrivers);
viewModel = new RoomWithRxJavaViewModel(getActivity().getApplication());
Disposable d = viewModel.getDrivers()
.subscribe(allusers ->
{
adapter = new DriverListAdapter(getContext(), (ArrayList<Driver>) allusers);
listViewDriver.setAdapter(adapter);
}, e -> {
//show err mes
}
);
}
}
The setup is pretty simple build.
I just have a custom linearlayout which I am planning to modify later. And yes, the relative layout for the listview is on purpose so I can easily modify my future button positions.
The result looks like this:
So the issue is that, altough the app bar at the top is visible, it wont hide when I scroll down my list (see picture above), eventough I am using app:liftOnScroll="true" and app:layout_scrollFlags="scroll|enterAlways|snap".
What am I missing exactly? Is it cause I use my custom linearlayout?
Putting the appbar before the custom linearlayout didn't change the output unfourntatly.

Disabling progress bar when URL fetch completes: A standard scenario

I have a rather popular scenario in which there is a fragment containing a progress bar and a ListView. I'd like to populate the ListView after fetching the data using Retrofit. Now, the progress bar needs to be made invisible once a response comes back in.
Would it be a good idea to store the view of the fragment layout inflated in onCreateView() as a member variable and use that variable to disable the progress bar in onResponse() (the callback is created in onCreate()), when the fetch succeeds?
Fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/source_items_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">
<com.gc.materialdesign.views.ProgressBarCircularIndeterminate
android:id="#+id/progress_bar"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="#1E88E5"
android:layout_gravity="center_horizontal"/>
<ListView android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/source_list"/>
</FrameLayout>
onCreate():
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItemList = new ArrayList<SourceItem>();
RestClient.get().getSources().enqueue(new Callback<SourceItemList>() {
#Override
public void onResponse(Response<SourceItemList> response, Retrofit retrofit) {
if (response.isSuccess()) {
disableProgressBar();
//...
}
}
#Override
public void onFailure(Throwable t) {
disableProgressBar();
return;
}
private void disableProgressBar() {
if (mView != null) {
mView.findViewById(R.id.progress_bar).setVisibility(View.INVISIBLE);
}
}
});
// ...
}
onCreateView():
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.fragment_sourceitem_list, viewGroup, false);
// ...
return mView;
}
Thanks
It is better to have progress bar initialized in onCreateView() rather than using view.findViewById() as it's an expensive operation.

Multiple Buttons in FloatingActionButton library

Hi I an trying to implement [FloatingActionButton][1] Library by makovkastar. (As it is backward compatible. It works fine with single FAB, but when 2 Buttons are added, the "List" seems to get attached to only one buttons.
fragment_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fab="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#android:color/transparent"
android:headerDividersEnabled="false"/>
<com.melnykov.fab.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:src="#drawable/ic_add_white_24dp"
fab:fab_colorNormal="#color/accent"
fab:fab_colorPressed="#color/accent_pressed"
fab:fab_colorRipple="#color/ripple"/>
<com.melnykov.fab.FloatingActionButton
android:id="#+id/fab2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:layout_margin="16dp"
android:src="#drawable/ic_add_white_24dp"
fab:fab_colorNormal="#color/accent"
fab:fab_colorPressed="#color/accent_pressed"
fab:fab_colorRipple="#color/ripple"/>
</FrameLayout>
MainActivity ListViewFragment Class
public static class ListViewFragment extends Fragment {
#SuppressLint("InflateParams")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_listview, container, false);
ListView list = (ListView) root.findViewById(android.R.id.list);
ListViewAdapter listAdapter = new ListViewAdapter(getActivity(),
getResources().getStringArray(R.array.countries));
list.setAdapter(listAdapter);
FloatingActionButton fab = (FloatingActionButton) root.findViewById(R.id.fab);
fab.attachToListView(list);
FloatingActionButton fab2 = (FloatingActionButton) root.findViewById(R.id.fab2);
fab2.attachToListView(list);
return root;
}
This is same code sample provided in that library:
When the list is scrolled, only one button (fab2 in this case) becomes invisible when scrolled down. I want both the buttons to react to scroll.
Any idea to anyone how this can be done?
Thanks in advance.
You can do this yourself, by making your fragment implement com.melnykov.fab.ScrollDirectionListener (also from the same package as the fab).
public static class ListViewFragment extends Fragment implements
com.melnykov.fab.ScrollDirectionListener {
private FloatingActionButton fab, fab2;
#SuppressLint("InflateParams")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_listview, container, false);
ListView list = (ListView) root.findViewById(android.R.id.list);
ListViewAdapter listAdapter = new ListViewAdapter(getActivity(),
getResources().getStringArray(R.array.countries));
list.setAdapter(listAdapter);
fab = (FloatingActionButton) root.findViewById(R.id.fab);
// this method expects a ScrollDirectionListener as second arg
// so use this for that parameter
fab.attachToListView(list, this);
fab2 = (FloatingActionButton) root.findViewById(R.id.fab2);
fab2.attachToListView(list, this);
return root;
}
#Override
public void onScrollDown() {
if (fab.isVisible() || fab2.isVisible()) {
fab.hide();
fab2.hide();
}
}
#Override
public void onScrollUp() {
if (!fab.isVisible() || !fab2.isVisible()) {
fab.show();
fab2.show();
}
}
}
I'm sure this should work, but in the case it doesn't you should open an issue to propose this possible bug to the developer.
Note
Android now has it's own implementation of the FloatingActionButton (and much more) in the design library. Include it in your project with this:
compile 'com.android.support:design:22.2.0'
Here is an excellent guide for using the new FAB with lists; it even includes use of the new CoordinatorLayout which should replace need for scroll listeners and such

"LayoutManager is already attached to a RecyclerView" error

I am trying to have multiple RecyclerViews in a layout but I get the following error: "LayoutManager is already attached to a RecyclerView"
The Java code is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_squad, container, false);
Activity parentActivity = getActivity();
final ObservableScrollView scrollView = (ObservableScrollView) view.findViewById(R.id.squad_scrollview);
final RecyclerView gkRecyclerView = (RecyclerView) view.findViewById(R.id.gk_recycler);
final RecyclerView coachRecyclerView = (RecyclerView) view.findViewById(R.id.coach_recycler);
coachRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(0)));
coachRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
coachRecyclerView.setHasFixedSize(false);
gkRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(1)));
gkRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
gkRecyclerView.setHasFixedSize(false);
scrollView.setTouchInterceptionViewGroup((ViewGroup) parentActivity.findViewById(R.id.container));
if (parentActivity instanceof ObservableScrollViewCallbacks) {
scrollView.setScrollViewCallbacks((ObservableScrollViewCallbacks) parentActivity);
}
return view;
}
The XML layout code is:
<com.github.ksoichiro.android.observablescrollview.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/squad_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/margin_medium"
>
<LinearLayout
android:id="#+id/squad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/seasons_scrollview"
android:divider="#drawable/nav_bar_divider"
android:elevation="#dimen/card_elevation"
android:orientation="vertical"
android:showDividers="middle">
<LinearLayout
android:id="#+id/coach_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_coach_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Coach"
android:textSize="#dimen/text_size_standard" />
<android.support.v7.widget.RecyclerView
android:id="#+id/coach_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin_small"
android:paddingBottom="#dimen/margin_small"
android:scrollbars="none">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:id="#+id/gk_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_gk_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Goalkeepers"
android:textSize="#dimen/text_size_standard" />
<android.support.v7.widget.RecyclerView
android:id="#+id/gk_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin_small"
android:paddingBottom="#dimen/margin_small"
android:scrollbars="none">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:id="#+id/def_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_def_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Defense"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
<LinearLayout
android:id="#+id/mid_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_mid_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Midfielders"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
<LinearLayout
android:id="#+id/for_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_for_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Forwards"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
</LinearLayout>
</com.github.ksoichiro.android.observablescrollview.ObservableScrollView>
The MyLinearLayoutManager is a custom LinearLayoutManager I found online in order to solve the wrap-content issue of the SDK LinearLayoutManager.
Is there any way I can have multiple RecyclerViews in a single layout? It seems that I cannot attach more than one LayoutManagers per layout.
Any assistance would be very welcome :)
I had this problem too. My Activity uses Tabs, with three fragments, when I go to third tab, and back to first (or second), this error is thrown.
After searching a lot, I found out that may be the garbage collector, because I was using a strong reference.
Since the constructor LinearLayoutManager uses the activity as the parameter (not the fragment), a Tabs Activity stays active during tabs changes.
Removing the local field in mLinearLayoutManager from the class, and using a weak reference, I could get rid of this problem:
before:
public class MyFragment1 extends Fragment
private LinearLayoutManager linearLayoutManager;
#Override
public void onCreate(Bundle savedInstanceState) {
linearLayoutManager = new LinearLayoutManager(getActivity());
(...)
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
(...)
mRecyclerView.setLayoutManager(linearLayoutManager);
}
}
I changed to:
public class MyFragment1 extends Fragment {
// private LinearLayoutManager linearLayoutManager;
#Override
public void onCreate(Bundle savedInstanceState) {
// linearLayoutManager = new LinearLayoutManager(getActivity());
(...)
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
(...)
mRecyclerView.setLayoutManager(
new LinearLayoutManager(getActivity()));
}
}
Just need to create a new instance:
RecyclerView recyclerView = new RecyclerView(getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()))
I faced this error when providing LayoutManager via Dagger. The solution is to replace layout manager injection with layout manager javax.inject.Provider injection.
#Inject
lateinit var layoutManager: Provider<RecyclerView.LayoutManager>
...
recyclerView.setLayoutManager(layoutManager.get())
I have the same problem as well. I work around it by setting null to LinearLayoutManager instance.
public class MyFragment extends Fragment {
protected LinearLayoutManager mLinearLayoutManager;
...
#Override
public void onDestroy() {
super.onDestroy();
if(mLinearLayoutManager != null) // Workaround: android.support.v7.widget.LinearLayoutManager is already attached to a RecyclerView
mLinearLayoutManager = null;
}
I opened FragmentB from FragmentA. Then returned back to FragmentA and got this exception. I found an error. I created in onCreate:
linearLayoutManager = LinearLayoutManager(requireContext())
and used in it onCreateView:
view.recycler_view.layoutManager = linearLayoutManager
Because linearLayoutManager hadn't recreated when we returned from FragmentB, RecyclerView used an old linearLayoutManager. So, I moved linearLayoutManager = LinearLayoutManager(requireContext()) to onCreateView.
In my case, I had declared a LinearLayoutManager globally and I was trying to attach the same instance of LinearLayoutManager to multiple RecyclerView's so I was getting this error.
The Solution is to attach different LayoutManager to each RecyclerView because one LayoutManager can only be attached to one Recyclerview.
I had this problem with Dagger2 and it was solved by removing the Scope Annotation.
I had annotated the code with some scope and when i removed the scope the problem was fixed.
I hope this would be helpful to you.
#MyScope #Provides static LinearLayoutManager provideLinearLayoutManager
I deleted the #MyScope.
This error I faced with Daggar2
and simply remove by using Provider before the LinearLayoutManager like;
#Inject
Provider <LinearLayoutManager> linearLayoutManager;
mViewDataBinding.rvResult.setLayoutManager(linearLayoutManager.get());
Possible options to fix this crash:
Create an instance of LayoutManager in onViewCreated of Fragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(context)
}
If it is necessary to have an instance of LayoutManager as a variable in Fragment, then detach the instance from RecyclerView in onDestroyView:
class MyFragment : Fragment() {
private val myLayoutManager by lazy { LinearLayoutManager(context) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = myLayoutManager
}
override fun onDestroyView() {
recyclerView.layoutManager = null
super.onDestroyView()
}
}
The second option will work, because the condition for throwing an exception will be false. Here is the code from the method setLayoutManager of RecyclerView:
...
if (layout != null) {
if (layout.mRecyclerView != null) { // will be false
throw new IllegalArgumentException("LayoutManager " + layout
+ " is already attached to a RecyclerView:"
+ layout.mRecyclerView.exceptionLabel());
}
mLayout.setRecyclerView(this);
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
}
}

Hide toolbar on scroll when the using a recyclerview inside a Fragment instead of an Activity

I'm trying to adapt the strategy for hiding / showing a toolbar (or any visual element) from the well explained and great article:
http://mzgreen.github.io/2015/02/15/How-to-hideshow-Toolbar-when-list-is-scroling%28part1%29/
But in my case I'm using a Fragment to hold the recycleview instead of the activity. My problem is that the padding is not being applied so the first element is under the toolbar, and I have also another strange behavior, as the toolbar is also under the statusbar. I don't know what is happening here.
The following are my "moving pieces":
BasicActivity.java: based on the one given on the previous post, but moving away the recycleview part as is going to be on the Fragment piece. Also it exposes the show and hide methods to allow the fragment to access it:
public class BasicActivity extends ActionBarActivity {
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container,new RecycleFragment())
.commit();
overridePendingTransition(0, 0);
initToolbar();
}
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
setTitle(getString(R.string.app_name));
mToolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
}
public void hideViews() {
mToolbar.animate().translationY(-mToolbar.getHeight()).setInterpolator(new AccelerateInterpolator(2));
}
public void showViews() {
mToolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
}
}
My activiy_basic.xml is the following:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="#layout/toolbar_actionbar" />
</FrameLayout>
The layout toolbar_actionbar.xml
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:clipToPadding="false"/>
The Fragment RecycleFragment.java:
public class RecycleFragment extends Fragment {
#Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler, container, false);
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initRecyclerView(view);
}
private void initRecyclerView(View view) {
RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
RecyclerAdapter recyclerAdapter = new RecyclerAdapter(createItemList());
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setOnScrollListener(new HidingScrollListener() {
#Override
public void onHide() {
((BasicActivity)getActivity()).hideViews();
}
#Override
public void onShow() {
((BasicActivity)getActivity()).showViews();
}
});
}
private List<String> createItemList() {
List<String> itemList = new ArrayList<>();
for(int i=0;i<20;i++) {
itemList.add("Item "+i);
}
return itemList;
}
}
And the layout for the fragment is just a recyclerview fragment_recycler.xml:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
The adapter and the viewholder for the recycler are the same as the article, and they doesn't affect the behavior.
What is wrong with the code?
UPDATE:
A MichaƂ Z. below pointed out. What was missing is the paddingTop and clipptoPadding on the Recyclerview view
So the final xml should be:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
And to solve the statusbar overlapping problem, it is needed to add a "fitsystemwindows" = "true" element on the activity layout. So it must be as the following:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<include layout="#layout/toolbar_actionbar" />
</FrameLayout>
UPDATE2
The fitSystemWindows is only needed if the theme is setting the statusbar as translucent
Your fragment_recycler.xml file is missing paddingTop and clipToPadding attributes.
It should look like this:
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize"
android:clipToPadding="false"/>
And also remove clipToPadding from your toolbar_actionbar.xml.

Categories

Resources