How to show progressbar like recyclerView - android

I am looking for a way to show a progressbar like the one below (which i just saw in recyclerView)

Please check this it will solve your problem
android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
// put your layout here
</android.support.v4.widget.SwipeRefreshLayout>
And activity code would be
SwipeRefreshLayout mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
refreshContent();
...
}

Related

how is the recyclerView maintains its scroll position without any extra coding

Created a simple activity which has a recyclerView and displays the data list. When turned on the setting's 'don't keep activity alive' and set 'Background process limit' to 'No background process'. Expect the acitivity will be killed by os in background.
When minimize the app and reopen it, saw the activity's onCreate() is called on a new instance and it does all again to create a new set of recyclerView and adapter with new datalist.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
mRecyclerView = findViewById(R.id.recyclerView);
setSupportActionBar(toolbar);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
}
But the ui still shows the item in last scrolled position (correctly restored).
Anyone knows how the previous position is transfered to the new recyclerView instance, etc.?
the layout:
<LinearLayout 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"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:titleTextColor="#android:color/white"
/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
the activity:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private ItemAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
mRecyclerView = findViewById(R.id. recyclerView);
setSupportActionBar(toolbar);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
}
#Override
protected void onResume() {
super.onResume();
new FetchItemASyncTask(this).execute();
// in the asyncTask it will do setup adapter when data ready
// mAdapter = new ItemAdapter(dataList)
// mRecyclerView.setAdapter(mAdapter);
}
}
This is part of the default saving of state that Android performs for many views. The only thing you need to do to enable this is to give the view an android:id attribute (if you take that id away, you'll notice that it no longer saves the scroll position). The same is true for e.g. the text entered into an EditText.

Recycler View Detect Swipe Up and Down

How can i set up my RecyclerView properly to detect swipe Up and Down?
When i place recycler.setOnTouchListener(this)
I get this warning: recyclerview has setontouchlistener but does not override perfoclick and nothing works.
Thank you.
recyclerView = (RecyclerView)rootview.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(layoutManager);
Adapter adapter=new
Adapter (List);
recyclerView.setAdapter(adapter);
You should be using SwipeRefreshLayout and handle the callback with setOnRefreshListener example.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
SwipeRefreshLayout mSwRefresh=findViewById(R.id.SwRefresh);;
mSwRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
//TODO:
}
});

How to use PullToRefresh without RecyclerView in android

I want use PullToRefresh but in my application I don't use recyclerview, and use this widget : android.support.v4.widget.NestedScrollView.
I should set pull to refresh to load new data in my application, how can I it?
Please don't offer to me for use RecyclerView, because I haven't use RecyclerView.
I want use android.support.v4.widget.NestedScrollView .
How can I it?
Use SwipeRefreshLayout
this.srl1 = (SwipeRefreshLayout) findViewById(R.id.srl);
if (srl1 != null) {
srl1.setColorSchemeResources(R.color.red, R.color.green, R.color.blue);
srl1.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Refresh();
}
});
}
XML CODE
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="#+id/srl"
>
</android.support.v4.widget.SwipeRefreshLayout>

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.

When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work

UPDATE: I thought it worked correctly. But after some test trouble still exists *sniff*
Then I made a simpler version to see what exactly happen and I get to know that the refreshing fragment which should have been detached still left there. Or exactly, the view of the old fragment left there, on top of the newer fragment. Since RecyclerView's background of my original app is not transparent, so It turned out what I said before.
END OF UPDATE
I have a MainActivity with layout like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="#+id/drawer_layout"
android:layout_width="match_parent" android:layout_height="match_parent">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout android:id="#+id/container" android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
If you're not building against API 17 or higher, use
android:layout_gravity="left" instead. -->
<!-- The drawer is given a fixed width in dp and extends the full height of
the container. -->
<fragment android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width" android:layout_height="match_parent"
android:layout_gravity="start" tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
The fragment ContentView I use to fill #id/container is configured as:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/tweet_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey_300"/>
</android.support.v4.widget.SwipeRefreshLayout>
And here is onCreateView() of ContentView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View inflatedView = inflater.inflate(R.layout.fragment_content, container, false);
mRecyclerView = (RecyclerView) inflatedView.findViewById(R.id.tweet_list);
mRecyclerView.setHasFixedSize(false);
mLinearLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
mRecyclerView.setLayoutManager(mLinearLayoutManager);
mTweetList = new ArrayList<Tweet>;
mAdapter = new TweetAdapter(mTweetList);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mSwipeRefreshLayout = (SwipeRefreshLayout) inflatedView.findViewById(R.id.contentView);
mSwipeRefreshLayout.setOnRefreshListener(
...
);
return inflatedView;
}
Then in MainActivity I switch the content to display by switching different ContentView. All looks good except one thing: when I switch ContentView fragments DURING refreshing by navigation drawer, then content freezes. But actually all things work as usual except you cannot see it.
Well... After some struggling I eventually solved this problem by myself, in a tricky way...
I just need to add these in onPause() :
#Override
public void onPause() {
super.onPause();
...
if (mSwipeRefreshLayout!=null) {
mSwipeRefreshLayout.setRefreshing(false);
mSwipeRefreshLayout.destroyDrawingCache();
mSwipeRefreshLayout.clearAnimation();
}
}
This issue seems to still be occurring in appcompat 22.1.1. Wrapping the SwipeRefreshLayout inside a FrameLayout solved this for me
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/tweet_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey_300" />
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
In addition to #zlm2012 answer, I noticed that this issue was reproduced under Support Library 21.0.0, but seems to be fixed right now at 21.0.3
The solution works, but I think it is better just put those lines into its own function, like:
public void terminateRefreshing() {
mSwipeRefreshLayout.setRefreshing(false);
mSwipeRefreshLayout.destroyDrawingCache();
mSwipeRefreshLayout.clearAnimation();
}
and call when switching the fragment.
Fragment prevFrag = fragmentManager.findFragmentById(drawerContainerId);
if(prevFrag instanceof SwipeRefreshFragment) {
((SwipeRefreshFragment)prevFrag).terminateRefreshing();
}
fragmentManager.beginTransaction().replace(drawerContainerId, fragment).commit();
It works! Just remove the transition from your fragment replacement, in my case I removed the following from my code:
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
Set clickable="true" in top parent layout... It may solve the problem.
For the time being, you can avoid the issue by:
public class FixedRefreshLayout extends SwipeRefreshLayout {
private static final String TAG = "RefreshTag";
private boolean selfCancelled = false;
public FixedRefreshLayout(Context context) {
super(context);
}
public FixedRefreshLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected Parcelable onSaveInstanceState()
{
if(isRefreshing()) {
clearAnimation();
setRefreshing(false);
selfCancelled = true;
Log.d(TAG, "For hide refreshing");
}
return super.onSaveInstanceState();
}
#Override
public void setRefreshing(boolean refreshing) {
super.setRefreshing(refreshing);
selfCancelled = false;
}
#Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if(hasWindowFocus && selfCancelled) {
setRefreshing(true);
Log.d(TAG, "Force show refreshing");
}
}
}
This has the added advantage of resuming the animation incase you decide to not switch the fragment (coming from some menu). It also ties in with the internal animation to make sure that the refreshing animation does not return if the network refresh has already completed.
Terminate SwipeRefresh whenever navigation menu item is clicked.
It worked.
private void selectItem(int position) {
mSwipeRefreshLayout.setRefreshing(false);
/*
Other part of the function
*/
}

Categories

Resources