How to add pull to update to AppBarLayout

I found that most of the material is about adding a "pull to refresh" to an area under the AppBarLayout such as SwipeRefreshLayout , I'm wondering how to do this in the AppBarLayout, which means:

enter image description here

When dropped, a pull-refresh indicator appears in the AppBarLayout.

how to implement it? thank

================= UPDATE ====================

I finally solved it my own way. Here is a link to a video recording a simple interface.

The key point is that I am rewriting the appbarlayout-spring-behavior from github. This is really helpful. In simple terms, I rewrote the AppBarLayoutSpringBehavior to add a Pull-To-Refresh callback on drag and add some logic to display the pull-refresh animation preventing simple animation back to its original state. After a while I say the behavior is to revive back.

Although the rewritten code seems ugly, it seems possible. I will refactor my code to be clean and modular

+7


source to share


4 answers


I wrote one nestrefresh repository where you can add a Pull Update for the header in the AppBarLayout. You can add pull to update the child in the ViewPager or pull to download additional. You can use ChildCoordinatorLayout in my repo to wrap the AppBarLayout if you only want to use AppBarLayout. But on scrolling, AppBarLayout cannot update because AppBarLayout does not dispatch a scroll event to the parent. So you can try RefreshBarLayout on the repo.



+1


source


You can try a view hierarchy like this

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingTop="?attr/actionBarSize">

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/appBar"/>
    </android.support.v4.widget.SwipeRefreshLayout>

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"/>
    </android.support.design.widget.AppBarLayout>
</RelativeLayout>

      



In your Java class, you can use your SwipeRefreshLayout like this

swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setProgressViewOffset(false, 0, (int) (swipeRefreshLayout.getPaddingTop() * 1.5));
swipeRefreshLayout.setOnRefreshListener(() -> {
    swipeRefreshLayout.setRefreshing(true);
    // long process here
    new Handler().postDelayed(() -> runOnUiThread(() -> swipeRefreshLayout.setRefreshing(false)), 2000);
});

      

0


source


EDIT Added ProgressBar inside AppBarLayout.

You need to wrap the ReyclerView with a SwipeRefreshLayout as you said and also add the ProgressBar to your custom ToolBar:

activity_main.xml

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.myapplication.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center">

                <TextView
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_gravity="start"
                    android:layout_weight="1"
                    android:gravity="start|center"
                    android:text="@string/app_name"
                    android:textColor="@android:color/white" />

                <ProgressBar
                    android:id="@+id/a_main_progress"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginRight="10dp"
                    android:visibility="invisible" />

            </LinearLayout>
        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/a_main_swipe"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/a_main_recycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </android.support.v7.widget.RecyclerView>

    </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>

      

You also need to set a listener to your MainActivity:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private SwipeRefreshLayout swipeRefreshLayout;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.a_main_swipe);
        progressBar = (ProgressBar) findViewById(R.id.a_main_progress);

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                progressBar.setVisibility(View.VISIBLE);
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        // Simulates a long running task (updating data)
                        swipeRefreshLayout.setRefreshing(false);
                        progressBar.setVisibility(View.INVISIBLE);
                    }
                }, 2000);
            }
        });

        MainAdapter mainAdapter = new MainAdapter(Arrays.asList("Hello", "World", "Bye"));
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.a_main_recycler);
        recyclerView.setAdapter(mainAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
    }
}

      

This is a simple adapter code if you need it too:

MainAdapter.java

public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> {

    private List<String> strings;

    public MainAdapter(List<String> strings) {
        this.strings = strings;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bind(strings.get(position));
    }

    @Override
    public int getItemCount() {
        return strings != null ? strings.size() : 0;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(android.R.id.text1);
        }

        public void bind(String s) {
            textView.setText(s);
        }
    }
}

      


This is the updated result:

ProgressBar result

0


source


I finally solved it my own way. Here is a link to a video recording a simple interface.

The key point is that I am rewriting the appbarlayout-spring-behavior from github. This is really helpful. In simple terms, I rewrote the AppBarLayoutSpringBehavior to add a Pull-To-Refresh callback on drag and add some logic to display the pull-refresh animation preventing simple animation back to its original state. After a while I say the behavior is to revive back.

Although the rewritten code seems ugly, it seems possible. I will refactor my code to be clean and modular

0


source







All Articles