Scroll the webPage Up and Down in RecyclerView in Android - android

I have implemented a webView within a recyclerView using Firebase as my database, but the problem is that the complete webPage is not visible, I cant scroll the web page up and down for the content and its stuck, I guess it is because of RecyclerView, please help so that I can scroll the page.
I am using Android Studio
webView class file:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_page);
webVieRes = (RecyclerView) findViewById(R.id.resycleWeb);
mdataRef = FirebaseDatabase.getInstance().getReference().child("weber");
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<post2web,post2webViewHolder> firebaseRecyclerAdapte = new FirebaseRecyclerAdapter<post2web,post2webViewHolder>(
post2web.class,
R.layout.web_card,
post2webViewHolder.class,
mdataRef
) {
#Override
protected void populateViewHolder(post2webViewHolder viewHolder, post2web model, int position) {
viewHolder.setWebViewPost(model.getWebViewPost());
}
};
webVieRes.setAdapter(firebaseRecyclerAdapte);
}
public static class post2webViewHolder extends RecyclerView.ViewHolder {
View mVie;
public post2webViewHolder(View itemView) {
super(itemView);
mVie = itemView;
}
public void setWebViewPost(String webViewPost) {
WebView post_web = (WebView) mVie.findViewById(R.id.webView_news);
post_web.loadUrl(webViewPost);
post_web.setWebViewClient(new WebViewClient());
}
}
RecyclerView xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:id="#+id/resycleWeb"/>
</LinearLayout>

Related

How to hide Progressbar when data is retrived from frirebase into recycloeview

I want to show a Progressbar when my data is being retrived from firebasedatabase into recyclerview, and hide it when its done. I searched online but no soln. works
here is my mainActivity
public class MemesSchool extends AppCompatActivity {
RecyclerView recyclerView;
MemeAdapter memeAdapter;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressBar = (ProgressBar) findViewById(R.id.pbmeme);
setContentView(R.layout.activity_memes_school);
getWindow().setStatusBarColor(getResources().getColor(R.color.buttonclr));
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.buttonclr)));
getSupportActionBar().setTitle("School Memes");
recyclerView = findViewById(R.id.rvm);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
FirebaseRecyclerOptions < mememodel > options =
new FirebaseRecyclerOptions.Builder < mememodel > ()
.setQuery(FirebaseDatabase.getInstance().getReference().child("Memedata"), mememodel.class)
.build();
memeAdapter = new MemeAdapter(options);
recyclerView.setAdapter(memeAdapter);
}
#Override
protected void onStart() {
super.onStart();
memeAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
memeAdapter.stopListening();
}
}
here is my MainActivity.XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".MemesSchool">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="#+id/rvm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foregroundGravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="#+id/pbmeme"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
my Adapterclass
public class MemeAdapter extends FirebaseRecyclerAdapter < mememodel, MemeAdapter.myViewHolder > {
public MemeAdapter(#NonNull FirebaseRecyclerOptions < mememodel > options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull myViewHolder holder, int position, #NonNull mememodel model) {
holder.username.setText(model.getNameuser());
holder.subuser.setText(model.getSubname());
holder.title.setText(model.getTitle());
Glide.with(holder.imgmeme.getContext()).load(model.getImagesurl())
.placeholder(R.drawable.logoinhanced)
.error(R.drawable.logoinhanced).into(holder.imgmeme);
}
#NonNull
#Override
public myViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(parent.getContext()).inflate(R.layout.memes_item, parent, false);
return new myViewHolder(view);
}
#Override
public void onDataChanged() {
}
#Override
public void onError(#NonNull DatabaseError error) {
super.onError(error);
}
class myViewHolder extends RecyclerView.ViewHolder {
ImageView imgmeme;
TextView username, subuser, title;
public myViewHolder(#NonNull View itemView) {
super(itemView);
imgmeme = itemView.findViewById(R.id.meme);
username = itemView.findViewById(R.id.nameuser);
subuser = itemView.findViewById(R.id.subname);
title = itemView.findViewById(R.id.titlememe);
}
}
}
There Is an Mothod called ONDATACHANGE() when should be in adapter class and i dont know how to control my adapter class from there ;
what should happen :- a Progressbar should be visible when i open the Activity and it should hide when the data is loaded in the RecyclerView !
One way to hide the progress bar when the data is loaded is to pass it to your adapter in its constructor, and then hide it in onDataChanged:
public class MemeAdapter extends FirebaseRecyclerAdapter < mememodel, MemeAdapter.myViewHolder > {
View progressBar;
public MemeAdapter(#NonNull FirebaseRecyclerOptions <mememodel> options, View progressBar) {
super(options);
this.progressBar = progressBar;
}
...
#Override
public void onDataChanged() {
progressBar.setVisibility(View.GONE)
}

ProgressBar while receiving Recyclerview data

I come to ask you for guidance with this, I have a recycler view, and what I want is that while the recyclerview is filled from the cloud firebase, a circular progressBar appears, and as soon as it loads, it disappears and the Recyclerview is loaded. I have already tried seeing various orientations around here but I cannot find it, with my code the progressbar is placed in a GONE way immediately, I imagine that you have to implement a ** CALLBACK ** or something like that, but no idea, I would appreciate that They will guide me a little with that of the CALLBACK, to see how I could implement it.
Borrow a photo and video from other users so they understand what I want to do
Demo Imagen ---> https://i.stack.imgur.com/JbLSi.png
Here is a video with what I want ---> Video
And here is the code that I am using
-------------------- 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MasvotingFragment">
<ProgressBar
android:id="#+id/progress_bar"
style="?android:progressBarStyle"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"/>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
android:visibility="gone"
android:layout_marginTop="5dp"
android:id="#+id/recyclerview_id">
</androidx.recyclerview.widget.RecyclerView>
</FrameLayout>
--------------------- Java ---------------------------
public class MasvotingFragment extends Fragment {
public MasvotingFragment() {
// Required empty public constructor
}
private FirebaseFirestore mDatabase;
private RecyclerView recyclerView ;
private Parcelable listState;
private RecyclerViewMasvotados mAdapter;
private ProgressBar mProgressBar;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_masvoting, container, false);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
mDatabase = FirebaseFirestore.getInstance();
recyclerView = view.findViewById(R.id.recyclerview_id);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mProgressBar = view.findViewById(R.id.progress_bar);
basedatocall();
if(listState!=null){
listState = Objects.requireNonNull(savedInstanceState).getParcelable("ListState");
}
}
private void basedatocall() {
Query query = mDatabase.collection("Post")
.orderBy("totales", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<masvotados> options = new FirestoreRecyclerOptions.Builder<masvotados>()
.setQuery(query, masvotados.class).build();
mAdapter = new RecyclerViewMasvotados(options);
mAdapter.notifyDataSetChanged();
recyclerView.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
mAdapter.startListening();
recyclerView.setAdapter(mAdapter);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onStart() {
super.onStart();
Objects.requireNonNull(recyclerView.getLayoutManager()).onRestoreInstanceState(listState);
mAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
if (mAdapter !=null){
mAdapter.stopListening();
}
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("ListState", Objects.requireNonNull(recyclerView.getLayoutManager()).onSaveInstanceState());
}
}
In advance Thank you all for your help, a hug

android nested RecyclerView issue: View.GONE doesn't instantly resize/redraw nested RecyclerView

I have an app that would benefit from a recyclerView nested in a recyclerView.
The issue I have though is that when I remove a textView outside on the recyclerView, the inner recyclerView doesn't redraw itself.
My app allows the user to read pages (RecyclerView with multiple paragraphs (nested RecyclerView)
The user can click the chapter title to get some added definitions/context displayed and if he clicks the definition it goes away.
The issue is when the definition goes away the nested RecyclerView doesn't redraw/re-size itself without a page swipe back and forth, could this be resolved?
I'm not android expert so I'm probably doing something wrong :S
My activity_main.xml
<?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">
<LinearLayout
android:id="#+id/pageContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_alignParentTop="true"
android:layout_above="#+id/definitionContainer">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/page"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="15dp"/>
</LinearLayout>
<RelativeLayout
android:id="#+id/definitionContainer"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="120dp"
android:visibility="gone"
android:onClick="hideDefinition">
<View android:id="#+id/devider" android:layout_marginTop="1dp" android:layout_marginBottom="1dp" android:background="#color/colorAccent" android:layout_width="match_parent" android:layout_height="2px" android:layout_alignParentTop="true"/>
<ScrollView
android:id="#+id/definitionScrollView"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:layout_below="#+id/devider"
android:background="#color/colorPrimaryDark"
android:onClick="hideDefinition">
<TextView
android:id="#+id/definitionTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:text="Lorem ipsum dolor sit amet, ..."
android:onClick="hideDefinition" />
</ScrollView>
</RelativeLayout>
</RelativeLayout>
My MainActivity.java
public class MainActivity extends AppCompatActivity {
#BindView(R.id.page) RecyclerView page;
#BindView(R.id.definitionContainer) RelativeLayout definitionContainer;
private ChapterContainerAdapter chapterAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
//if (page == null) page = findViewById(R.id.page);
page.setLayoutManager(new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false));
page.setItemAnimator(new DefaultItemAnimator());
chapterAdapter = new ChapterContainerAdapter(this);
page.setAdapter(chapterAdapter);
SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(page);
}
public void showDefinition (View v) {
definitionContainer.setVisibility(View.VISIBLE);
}
public void hideDefinition (View v) {
definitionContainer.setVisibility(View.GONE);
}
}
My recyclerView Adapter is very basic:
public class ChapterContainerAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private Context ctx;
static final String pageData[] = {"Page 1", "Page 2", "Page 3", "Page 4", "Page 5"};
public ChapterContainerAdapter(Context ctxIn) { ctx = ctxIn; }
#Override public void onBindViewHolder(BaseViewHolder holder, int position) { holder.onBind(position); }
#Override public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ChapterContainerAdapter.ChapterAdapterViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_page, parent, false));
}
#Override public int getItemCount() { return pageData.length; }
public class ChapterAdapterViewHolder extends BaseViewHolder {
#BindView(R.id.chapterTitle)
TextView chapterTitle;
#BindView(R.id.chapterContentRecyclerView)
RecyclerView chapterContentRecyclerView;
ParagraphAdapter paragraphAdapter;
public ChapterAdapterViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
protected void clear() { chapterTitle.setText(""); }
public void onBind(int position) {
super.onBind(position);
initiateVerseRecyclerView(position);
}
private void initiateVerseRecyclerView (int position) {
chapterTitle.setText(pageData[position]);
chapterContentRecyclerView.setLayoutManager(new LinearLayoutManager(ctx, RecyclerView.VERTICAL, false));
chapterContentRecyclerView.setItemAnimator(new DefaultItemAnimator());
paragraphAdapter = new ParagraphAdapter(ctx, position);
chapterContentRecyclerView.setAdapter(paragraphAdapter);
}
}
}
Did you to call notifyDataSetChange manually on adapter after removing view?

How to use SwipeDismissBehavior.OnDismissListener on RecyclerView

I am trying to use the SwipeDismissBehavoir from design support library. I've list items in RecyclerView and swiping an item have to dismiss (like google inbox app) .
I've set the listener for the RecyclerView items but the SwipeDismissBehavior onDismiss listener is not getting called.
SwipeDismissBehavior behavior = new SwipeDismissBehavior();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams)mItemLayout.getLayoutParams();
params.setBehavior(behavior);
behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
#Override
public void onDismiss(View view) {
}
#Override
public void onDragStateChanged(int i) {
}
});
mItemLayout.setLayoutParams(params);
Here is example how delete row by swipe
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
// init layout manager
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
final ArrayList<String> list = new ArrayList<String>();
list.add("Item1");
list.add("Item2");
list.add("Item3");
list.add("Item4");
list.add("Item5");
list.add("Item6");
final MyAdapter adapter = new MyAdapter(list);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
ItemTouchHelper swipeToDismissTouchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
// callback for drag-n-drop, false to skip this feature
return false;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// callback for swipe to dismiss, removing item from data and adapter
list.remove(viewHolder.getAdapterPosition());
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
});
swipeToDismissTouchHelper.attachToRecyclerView(recyclerView);
}
Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
ArrayList<String> dataset_;
public static class MyViewHolder extends RecyclerView.ViewHolder{
public Button mBtn;
public TextView mTextView2;
public MyViewHolder(View v){
super(v);
mBtn = (Button) itemView.findViewById(R.id.delete);
mTextView2 = (TextView) itemView.findViewById(R.id.textView2);
}
}
public MyAdapter (ArrayList<String> dataset){
dataset_ = dataset;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view,parent,false);
MyViewHolder myViewHolder = new MyViewHolder(v);
return myViewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder,int position){
holder.mTextView2.setText(dataset_.get(position));
}
#Override
public int getItemCount(){
return dataset_.size();
}
}
Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="vertical"
android:padding="16dp">
<TextView
style="?android:listSeparatorTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/heading_dismissable_recycler_view" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Item in RecyclerView
<?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">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Medium Text"
android:id="#+id/textView2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/delete"
android:text="Delete"
android:layout_marginLeft="150dp"
android:visibility="invisible" />
</LinearLayout>
</LinearLayout>
Tried with single view.
I can know the view was dismissed, but I'm wondering how to restore the view like Gmail.
Layout:
<android.support.design.widget.CoordinatorLayout
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"
android:id="#+id/coordinatorLayout"
tools:context=".MainActivity">
<android.support.v7.widget.CardView
android:id="#+id/cardView"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="Haha"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v7.widget.CardView>
</android.support.design.widget.CoordinatorLayout>
Activity:
public class MainActivity extends AppCompatActivity {
private CoordinatorLayout coordinatorLayout;
private CardView cardView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
cardView = (CardView) findViewById(R.id.cardView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) cardView.getLayoutParams();
final SwipeDismissBehavior<CardView> behavior = new SwipeDismissBehavior();
behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END);
behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
#Override
public void onDismiss(final View view) {
Snackbar.make(coordinatorLayout, "Done", Snackbar.LENGTH_LONG)
.show();
}
#Override
public void onDragStateChanged(int i) {
}
});
params.setBehavior(behavior);
cardView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return behavior.onTouchEvent(coordinatorLayout, cardView, event);
}
});
}
}
I have succeeded implementing the support library SwipeDismissBehavior and it actually requires CoordinatorLayout inside of each inflated card view layout. I haven't noticed any performance issues so far, so I assume CoordinatorLayout is not so heavy for the UI. There is probably a better way, but I still haven't found it.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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="wrap_content"
android:background="#FF0000">
<LinearLayout
android:id="#+id/card_content_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#FFFFFF"
android:padding="20dp">
<TextView
android:id="#+id/card_context_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test text"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
In the constructor of the RecyclerView.ViewHolder implementation class (which is inside the Adapter) I have added:
View cardContentLayout = view.findViewById(R.id.card_content_layout);
SwipeDismissBehavior<View> swipeDismissBehavior = new SwipeDismissBehavior<>();
swipeDismissBehavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_END_TO_START);
swipeDismissBehavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
#Override
public void onDismiss(View view) {
int adapterPosition = getAdapterPosition();
deleteListener.onDismissGesture(view, adapterPosition);
}
#Override
public void onDragStateChanged(int state) { }
});
CoordinatorLayout.LayoutParams coordinatorParams = (CoordinatorLayout.LayoutParams) cardContentLayout.getLayoutParams();
coordinatorParams.setBehavior(swipeDismissBehavior);
cardContentLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return swipeDismissBehavior.onTouchEvent((CoordinatorLayout) itemView, cardContentLayout, event);
}
});

SwipeRefreshLayout is hidden on empty RecyclerView

I have a Fragment with a SwipeRefreshLayout and then RecyclerView as child.
When the Fragment is committed, it starts talking to a server in order to retrieve some data and populate a CustomAdapter which will serve the RecyclerView.
The user can refresh the content by swiping down or pressing a button on the ActionBar. In the latter case, I manually call swipeRefreshLayout.setRefreshing(true). So no troubles until now.
The problem arises when I manually call the refresh state during the first loading of the RecyclerView (onStart()).
The progress indicator is not showed up and I assume because the RecyclerView is still empty since it requires some seconds to retrieve all the data...
I leave you some code.
Fragment code:
public class MyFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_stop, container, false);
mRecyclerView = (RecyclerView) mView.findViewById(R.id.recyclerView1);
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//SwipeRefreshLayout retrieved and configured
swipeLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorSchemeResources(
R.color.primaryColor,
R.color.cyan_500,
R.color.light_green_500,
R.color.amber_500);
return mView;
}
...
#Override
public void onStart() {
super.onStart();
executeSchedule(); //First execution and data loading.
}
...
#Override
public void onRefresh() {
executeSchedule();
}
...
public void executeSchedule() {
new Schedule().execute();
}
private class Schedule extends AsyncTask<Void, Void, Void> {
...
#Override
protected void onPreExecute() {
super.onPreExecute();
if(!swipeLayout.isRefreshing()) {
swipeLayout.setRefreshing(true); //set refresh state
}
}
#Override
protected Void doInBackground(Void... params) {
...
}
#Override
protected void onPostExecute(Void result) {
adap = new CustomAdapter(getActivity(), ...);
mRecyclerView.setAdapter(adap);
swipeLayout.setRefreshing(false);
}
}
XML code:
<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">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingBottom="2dp"
android:layout_marginTop="5dp"
android:divider="#e0e0e0"
tools:context=".MyFragment" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
</FrameLayout>
What would be the best practice to address this situation?
Adding a second dummy SwipeRefreshLayout? Immediately force an empty adapter?
I had a problem with SwipeRefreshLayout not working with an empty recycler, so I created a very simple empty adapter.
public class EmptyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
#Override
public int getItemCount() {
return 0;
}
}
I just wrap RecyclerView with RelativeLayout inside SwipeRefreshLayout and the problem is solved.
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
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="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
</android.support.v4.widget.SwipeRefreshLayout>
You need to call measure method before call setRefreshing(true).
Take a look at: SwipeRefreshLayout no animation on fragment creation. Maybe it can be helpful.

Categories

Resources