Android custom component series [7]-advanced practices (4)

Source: Internet
Author: User
Tags gety

In the previous "Android custom components series [6] -- advanced practice (3)", we added the process knowledge about event distribution in Android, in this article, we will analyze the implementation of the drop-down PinnedHeaderExpandableListView.

I. What is the role of the OnGiveUpTouchEventListener interface in StickyLayout?

 

    public interface OnGiveUpTouchEventListener {        public boolean giveUpTouchEvent(MotionEvent event);    }
In StickyLayout, you can set the listener as follows:

 

 

    public void setOnGiveUpTouchEventListener(OnGiveUpTouchEventListener l) {        mGiveUpTouchEventListener = l;    }
This method is actually a hook method. In OnGiveUpTouchEventListener, an abstract method (not implemented) giveUpTouchEvent is defined. Then, the MainActivity inherits the OnGiveUpTouchEventListener interface to implement the specific logic.

 

 

    @Override    public boolean giveUpTouchEvent(MotionEvent event) {        if (expandableListView.getFirstVisiblePosition() == 0) {            View view = expandableListView.getChildAt(0);            if (view != null && view.getTop() >= 0) {                return true;            }        }        return false;    }
Logic in this method: Get the first visible item in ExpandableListView. If it is the first visible item in its subview, it indicates that you should first slide the Header section above (let it expand ).

 

What is the difference between true and false returned here? Look down

 

    @Override    public boolean onInterceptTouchEvent(MotionEvent event) {        int intercepted = 0;        int x = (int) event.getX();        int y = (int) event.getY();        switch (event.getAction()) {        case MotionEvent.ACTION_DOWN: {            mLastXIntercept = x;            mLastYIntercept = y;            mLastX = x;            mLastY = y;            intercepted = 0;            break;        }        case MotionEvent.ACTION_MOVE: {            int deltaX = x - mLastXIntercept;            int deltaY = y - mLastYIntercept;            if (mStatus == STATUS_EXPANDED && deltaY <= -mTouchSlop) {                intercepted = 1;            } else if (mGiveUpTouchEventListener != null) {                if (mGiveUpTouchEventListener.giveUpTouchEvent(event) && deltaY >= mTouchSlop) {                    intercepted = 1;                }            }            break;        }        case MotionEvent.ACTION_UP: {            intercepted = 0;            mLastXIntercept = mLastYIntercept = 0;            break;        }        default:            break;        }        Log.d(TAG, intercepted= + intercepted);        return intercepted != 0;    }
There are several codes in ACTION_MOVE of the event Interception Method in the StickyLayout class:

 

 

            if (mStatus == STATUS_EXPANDED && deltaY <= -mTouchSlop) {                intercepted = 1;            } else if (mGiveUpTouchEventListener != null) {                if (mGiveUpTouchEventListener.giveUpTouchEvent(event) && deltaY >= mTouchSlop) {                    intercepted = 1;                }            }
Now you should understand it, huh, huh. STATUS_EXPANDED is a status value, which indicates that the Header is expanded. If the Header is collapsed, the returned value of giveUpTouchEvent is determined. If giveUpTouchEvent returns true, the list is all pulled down, in this case, expand the Header section. If false is returned, the list should be dropped rather than the Header part.

 

II. Implementation of OnScrollLister in PinnedHeaderExpandableListView

 

    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        if (mHeaderView != null && scrollState == SCROLL_STATE_IDLE) {            int firstVisiblePos = getFirstVisiblePosition();            if (firstVisiblePos == 0) {                mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight);            }        }        if (mScrollListener != null) {            mScrollListener.onScrollStateChanged(view, scrollState);        }    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem,            int visibleItemCount, int totalItemCount) {        if (totalItemCount > 0) {            refreshHeader();        }        if (mScrollListener != null) {            mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);        }    }
OnScrollListener is a rolling event of ListView.

 

In onScrollStateChanged (AbsListView view, int scrollState), scrollState has three states:

1. SCROLL_STATE_FLING: Start rolling

2. SCROLL_STATE_TOUCH_SCROLL: Rolling

3. SCROLL_STATE_IDLE: stopped

The onScroll () method always calls back when the list is rolled. The callback is stopped only when the rolling is stopped. In addition, the callback is also performed once when the list is clicked. OnScrollStateChanged indicates the callback when the preceding three States change. The callback sequence is as follows:

 

  1. 1st times: scrollState = SCROLL_STATE_TOUCH_SCROLL (1) Rolling
  2. 2nd times: scrollState = SCROLL_STATE_FLING (2) the finger throws (the finger slides hard before leaving the screen)
  3. 3rd Times: scrollState = SCROLL_STATE_IDLE (0) Stop rolling
  4. In the OnScrollStateChanged method above, the list header is laid out again (drawn) after the rolling is stopped. The onScroll method is mainly used to call the refreshHeader () method mentioned above to call back and refresh the list header.
  5. 4. What should I do if the following list header is placed on the top of the list?
  6.     protected void refreshHeader() {        if (mHeaderView == null) {            return;        }        int firstVisiblePos = getFirstVisiblePosition();        int pos = firstVisiblePos + 1;        int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos));        int group = getPackedPositionGroup(getExpandableListPosition(pos));        if (group == firstVisibleGroupPos + 1) {            View view = getChildAt(1);            if (view.getTop() <= mHeaderHeight) {                int delta = mHeaderHeight - view.getTop();                mHeaderView.layout(0, -delta, mHeaderWidth, mHeaderHeight - delta);            }        } else {            mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight);        }        if (mHeaderUpdateListener != null) {            mHeaderUpdateListener.updatePinnedHeader(firstVisibleGroupPos);        }    }
    You can see in the refreshHeader () method that, first, judge whether there are multiple list headers. If so, reset the position of the following list header to the "standard position ", in this way, I feel like there is a kind of top-up feeling.
  7. Iii. How to expand and collapse the list
  8.     @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        int x = (int) ev.getX();        int y = (int) ev.getY();        Log.d(TAG, dispatchTouchEvent);        int pos = pointToPosition(x, y);        if (y >= mHeaderView.getTop() && y <= mHeaderView.getBottom()) {            if (ev.getAction() == MotionEvent.ACTION_DOWN) {                mActionDownHappened = true;            } else if (ev.getAction() == MotionEvent.ACTION_UP) {                int groupPosition = getPackedPositionGroup(getExpandableListPosition(pos));                if (groupPosition != INVALID_POSITION && mActionDownHappened) {                    if (isGroupExpanded(groupPosition)) {                        collapseGroup(groupPosition);                    } else {                        expandGroup(groupPosition);                    }                    mActionDownHappened = false;                }                            }            return true;        }        return super.dispatchTouchEvent(ev);    }
    We can see that the event Distribution Function in PinnedHeaderExpandableListView contains the following code:
  9. if (y >= mHeaderView.getTop() && y <= mHeaderView.getBottom()) 
    Height limit (in the header of the List)
  10. if (isGroupExpanded(groupPosition)) {                        collapseGroup(groupPosition);                    } else {                        expandGroup(groupPosition);                    }

    1.  



       

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.