Android SwipeRefreshLayout pull-down refresh and pull-up loading + sliding Deletion

Source: Internet
Author: User

Android SwipeRefreshLayout pull-down refresh and pull-up loading + sliding Deletion

SwipeRefreshLayout-the pull-down refresh control officially proposed by Google, which is widely used in various apps. I always wanted to achieve a sliding deletion effect similar to QQ, which not only supports pull-down refresh, but also pull-up and load. I found a lot of information online and finally achieved the following results:

Next, let's take a look at the specific implementation process.

1. Interface layout: <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Vc3ryb25np1_vcd4ncjxwcmugy2xhc3m9 "brush: java;"> <code class = "hljs avrasm"> <com. example. swiperefreshlayoutdemo. refreshlayout xmlns: android = "http://schemas.android.com/apk/res/android" android: id = "@ + id/swipe_container" android: layout_width = "match_parent" android: layout_height = "match_parent"> <com. example. swiperefreshlayoutdemo. qqlistview android: id = "@ + id/list" android: layout_width = "match_parent" android: layout_height = "wrap_content"> </com. example. swiperefreshlayoutdemo. qqlistview> </com. example. swiperefreshlayoutdemo. refreshlayout> </code>

To implement pull-up loading and sliding deletion, custom RefreshLayout and Listview are used.
2. Code implementation:

SwipeRefreshLayout has two methods:Implement slide listeningTo load more functions when sliding to the bottom. One isListen to the pull-on action through the event Transfer MechanismAnd load more functions. First, let's look at the first loading principle:

Custom SwipeRefreshLayout:

// Inherits from SwipeRefreshLayout, so that more functions can be loaded when sliding to the bottom. public class RefreshLayout extends SwipeRefreshLayout implements OnScrollListener {// listview instance private ListView mListView; // listener of the uploadlistener interface, and the uploadlistener of the private OnLoadListener operation at the bottom; // footer private View mListViewFooter in ListView loading; // whether it is being loaded (pull more) private boolean isLoading = false; public RefreshLayout (Context context) {this (context, null);} public RefreshLayout (Context context, AttributeSet attrs) {super (context, attrs); // a circular progress bar mListViewFooter = LayoutInflater. from (context ). inflate (R. layout. listview_footer, null, false) ;}@ Override protected void onLayout (boolean changed, int left, int top, int right, int bottom) {super. onLayout (changed, left, top, right, bottom); // initialize the ListView object if (mListView = null) {getListView ();}} // obtain the ListView object private void getListView () {int childs = getChildCount (); if (childs> 0) {View childView = getChildAt (0); if (childView instanceof ListView) {mListView = (ListView) childView; // sets the scroll listener to ListView mListView. setOnScrollListener (this) ;}}// set the loading status, add or remove the public void setLoading (boolean loading) {isLoading = loading; if (isLoading) {mListView. addFooterView (mListViewFooter);} else {mListView. removeFooterView (mListViewFooter) ;}// sets the listener public void setOnLoadListener (OnLoadListener loadListener) {mOnLoadListener = loadListener;} @ Override public void listener (AbsListView view, int scrollState) {}@ Override public void onScroll (AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {// determines whether it is at the bottom and is not in the status of loading data if (mListView. getLastVisiblePosition () = mListView. getAdapter (). getCount ()-1 & isLoading = false) {// first set the loading status setLoading (true); // call the method mOnLoadListener to load data. onLoad () ;}}// load more interfaces public interface OnLoadListener {public void onLoad ();}}

The annotations are clearly written to implement the sliding listener, initialize the listview, and write the loading task interface and method. Note the following parameters in the sliding listener method:
FirstVisibleItemPosition of the first listItem displayed on the current screen in the entire listView (subscript starts from 0)
VisibleItemCountIndicates the total number of listitems that can be seen on the current screen (the number of listitems displayed in part is also calculated ).
TotalItemCountTotal number of listitems in ListView
ListView. getLastVisiblePosition ()Indicates the position of the last ListItem on the current screen (the last ListItem must be fully displayed) in the entire ListView (subscript starts from 0)
At the beginning, the system only determines whether to slide to the bottom and does not judge the loading status. As a result, the program runs down and data is always loaded at the bottom. Later, the judgment is added. By default, data is not loaded. If isLoading is set to false, it is set to true when sliding to the bottom to load data. After loading is complete, it is set to false and loaded.

Next is the second loading principle:

Public class RefreshLayout extends SwipeRefreshLayout {// listview instance private ListView mListView; // pull up interface listener, pull up the loading operation private OnLoadListener mOnLoadListener at the bottom; // footer private View mListViewFooter in ListView loading; // whether or not it is loading (pull more) private boolean isLoading = false; // The y coordinate private int mYDown when pressing; // The y coordinate private int mLastY when lifting; // The private int mTouchSlop when sliding to the bottom; public RefreshLayout (Context context) {this (context, null);} public RefreshLayout (Context context, AttributeSet attrs) {super (context, attrs); mTouchSlop = ViewConfiguration. get (context ). getScaledTouchSlop (); mListViewFooter = LayoutInflater. from (context ). inflate (R. layout. listview_footer, null, false) ;}@ Override protected void onLayout (boolean changed, int left, int top, int right, int bottom) {super. onLayout (changed, left, top, right, bottom); // initialize the ListView object if (mListView = null) {getListView ();}} // obtain the ListView object private void getListView () {int childs = getChildCount (); if (childs> 0) {View childView = getChildAt (0); if (childView instanceof ListView) {mListView = (ListView) childView ;}} public boolean dispatchTouchEvent (MotionEvent event) {final int action = event. getAction (); switch (action) {case MotionEvent. ACTION_DOWN: // press mYDown = (int) event. getRawY (); break; case MotionEvent. ACTION_MOVE: // move mLastY = (int) event. getRawY (); break; case MotionEvent. ACTION_UP: // lift if (mYDown-mLastY)> = mTouchSlop & isLoading = false) {// set the status setLoading (true); // mOnLoadListener. onLoad () ;}break; default: break;} return super. dispatchTouchEvent (event);} // set the loading status public void setLoading (boolean loading) {isLoading = loading; if (isLoading) {mListView. addFooterView (mListViewFooter);} else {mListView. removeFooterView (mListViewFooter) ;}// sets the listener public void setOnLoadListener (OnLoadListener loadListener) {mOnLoadListener = loadListener ;} // load more interfaces: public interface OnLoadListener {public void onLoad ();}}

The initialization data is the same. The difference is that two Y coordinates are recorded, one is pressed and the other is lifted to determine the pull action when sliding to the bottom.GetScaledTouchSlopIt is a distance, indicating that when moving, the control starts to move more than this distance. If the distance is smaller than this distance, the mobile control is not triggered. For example, viewpager uses this distance to determine whether the user is turning pages.
Then, the three actions of the view are obtained through the event transfer mechanism:
MotionEvent. ACTION_DOWNPress View to start all events
MotionEvent. ACTION_MOVESlide event
MotionEvent. ACTION_UPCorresponds to down, indicating to be lifted
When the sliding distance is greater than or equal to the required distance and the loading status is false, set the status and load data. The principle is the same as above.

The following is the MainActivity code:

Public class MainActivity extends Activity implements OnRefreshListener, OnLoadListener {private RefreshLayout swipeLayout; private QQListView listView; private MyAdapter adapter; private List  List = new ArrayList  (); Private int y = 11; @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); initView (); setData (); setListener ();} private void initView () {swipeLayout = (RefreshLayout) findViewById (R. id. swipe_container); swipeLayout. setOnRefreshListener (this); swipeLayout. setColorScheme (android. r. color. holo_blue_bright, android. r. color. holo_green_light, android. r. color. holo_orange_light, android. r. color. holo_red_light);} private void setData () {list = new ArrayList <> (); for (int I = 3; I <12; I ++) {list. add (I);} listView = (QQListView) findViewById (R. id. list); adapter = new MyAdapter (this, list); listView. setAdapter (adapter); listView. setOnItemClickListener (new OnItemClickListener () {@ Override public void onItemClick (AdapterView Arg0, View arg1, int position, long arg3) {Toast. makeText (getApplicationContext (), "This is the first" + String. valueOf (position + 1) + "item", Toast. LENGTH_SHORT ). show () ;}}); listView. setDelButtonClickListener (new DelButtonClickListener () {@ Override public void clickHappend (int position) {list. remove (position); refresh () ;}}) ;} private void setListener () {swipeLayout. setOnRefreshListener (this); swipeLayout. setOnLoadListener (this) ;}@ Override public void onRefresh () {swipeLayout. postDelayed (new Runnable () {@ Override public void run () {// update the data list. clear (); y = 12; for (int I = 0; I <13; I ++) {list. add (I) ;} refresh (); // call this method after update to end refreshing swipeLayout. setRefreshing (false); }}, 1000) ;}@ Override public void onLoad () {swipeLayout. postDelayed (new Runnable () {@ Override public void run () {// update data y ++; list. add (y); refresh (); // call this method after update to end refreshing swipeLayout. setLoading (false) ;}}, 1000) ;}private void refresh () {adapter. setList (list); adapter. notifyDataSetChanged ();}}  

Implement the built-in drop-down refresh interface method and the pull-up and load method we have defined, and then perform business operations in their respective methods. Here I simulate a simple numeric refresh. By now, SwipeRefreshLayout's pull-down refresh and pull-up loading have been completed. The last step is SwipeRefreshLayout's sliding deletion.

Here, the sliding deletion refers to the blog of Hongyang, which provides detailed code comments and explanations:

The principle of sliding to delete an item is to get the position of the item through the callback, then perform the delete operation, and update the adapter. The difficulty isSolve the conflict between the pull-up and pull-down refresh operations and the listview slide-deletion operations

@ Override public boolean dispatchTouchEvent (MotionEvent ev) {// obtain the action type int action = ev. getAction (); int x = (int) ev. getX (); int y = (int) ev. getY (); switch (action) {case MotionEvent. ACTION_DOWN: xDown = x; yDown = y;/*** if the current popupWindow is displayed, hide it directly, and then shield the downloading of the ListView touch event */if (mPopupWindow. isShowing () {dismissPopWindow (); return false;} // obtain the position of the item when the current finger is pressed. mCurrentViewPos = pointToPosition (x Down, yDown); View view = getChildAt (mCurrentViewPos-getFirstVisiblePosition (); mCurrentView = view; break; case MotionEvent. ACTION_MOVE: xMove = x; yMove = y; int dx = xMove-xDown; int dy = yMove-yDown; /*** determine whether it is a slide from right to left */if (xMove <xDown & Math. abs (dx)> touchSlop & Math. abs (dy) <touchSlop) {// Log. e (TAG, "touchslop =" + touchSlop + ", dx =" + dx + // ", dy =" + dy); isSlidin G = true;} break;} return super. dispatchTouchEvent (ev) ;}@ Override public boolean onTouchEvent (MotionEvent ev) {int action = ev. getAction ();/*** if it is a slide from the right to the left, the corresponding */if (isSliding) {switch (action) {case MotionEvent. ACTION_MOVE: int [] location = new int [2]; // obtain the position of the current item x and y mCurrentView. getLocationOnScreen (location); // sets the animation mPopupWindow of the popupWindow. setAnimationStyle (R. style. popwindow_delete _ Btn_anim_style); mPopupWindow. update (); mPopupWindow. showAtLocation (mCurrentView, Gravity. LEFT | Gravity. TOP, location [0] + mCurrentView. getWidth (), location [1] + mCurrentView. getHeight ()/2-mPopupWindowHeight/2); // You can call back mDelBtn from the delete button. setOnClickListener (new OnClickListener () {@ Override public void onClick (View v) {if (mListener! = Null) {mListener. clickHappend (mCurrentViewPos); mPopupWindow. dismiss () ;}}); // Log. e (TAG, "mPopupWindow. getHeight () = "+ mPopupWindowHeight); break; case MotionEvent. ACTION_UP: isSliding = false;} // The itemClick event of the screen during the sliding period to avoid conflicting return true;} return super. onTouchEvent (ev );}

Through the dispatchTouchEvent event transfer mechanism, you can set whether to respond to user slide and determine whether to respond in onTouchEvent. If the response is received, popupWindow is displayed as an animation. Of course, if there is a PopupWindow on the screen, the scrolling of the screen ListView and the clicking of the Item, and the clicking event of the screen Item will be blocked when sliding from right to left.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.