Simple horizontal ListView implementation (version 3.0), listviewversion

Source: Internet
Author: User

Simple horizontal ListView implementation (version 3.0), listviewversion

Version 2 is just a simple implementation. When the finger is pressed, The listView Item moves a certain distance to the left and does not scroll along with the left and right of the finger, in this version 3.0, the target will be rolled with the finger movement: When the finger moves to the left, the listView will scroll to the left; when the finger moves to the right, the listView will scroll to the right; before getting started, let's talk about the preparation knowledge and related methods.

When adding a View before version2.0, addView was used and finally called the addViewInner method. After querying the viewGroup source code, we found that there was an addViewInLayout method. The api description is as follows: Adds a view during layout, this is usefule if in your onLayout method. the lateral listView is the View added in onLayout, so it is changed to addViewInLayout from now on. In ViewGrouup, an array of views (mChildren) is provided. The addView method calls addVew (View view, index). The default value of the index is-1, indicating that it is added to the final side of the view array mChildren. The second parameter of the addViewInLaout method is this index. If the index is negative, the final side of the View method array will be taken. (In actual code processing, this is the insert operation of the array, very simple source code). When the index is positive, insert the View to the index position in the array, and move the elements in the mChildren of the corresponding View array behind, of course, the removeViewInLayout method is also available when the corresponding View is deleted; in fact, getChildAt (int index) is to get the View of the corresponding index from the array mChildrenCount, so the core idea of left and right sliding is coming out:

1) When you scroll left, add the View to be rolled out on the right to the end of the mChildren array, and display it on the page as the View on the right of the screen, at the same time, a rightIndex is provided to indicate the adapter. position of getView. That is, addViewInlayout (view,-1, view. getLayoutParams, true ),

2) When you scroll to the right, the front position of the mChildren array 0 to be added to the View to be rolled out on the left is displayed as the View on the left of the screen, colleagues provide a left to represent the adapter. the position parameter of getView. AddViewInlayout (view, 0, view. getLayoutParams, true). The Code is as follows:

Private void addRightChildViews (int dianceX) {// 2. display the Item as much as possible on the screen. Note that at the beginning, there was no View rightChildView = getChildAt (getChildCount ()-1); // you can get the distance from the Right Border of this childView to the Left Border of parentView. int rightEdge = rightChildView! = Null? RightChildView. getRight (): 0; while (rightEdge + dianceX <getWidth () & rightIndex <listAdapter. getCount () {View child = listAdapter. getView (rightIndex, null, null); child = measureChild (child); addViewInLayout (child,-1, child. getLayoutParams (), true); rightEdge + = child. getMeasuredWidth (); rightIndex ++ ;}} private void addLeftChildViews (int dianceX) {View leftChildView = getChildAt (0); in T leftEdge = leftChildView! = Null? LeftChildView. getLeft (): 0; while (leftEdge + dianceX> 0 & leftIndex> = 0) {View child = listAdapter. getView (leftIndex, null, null); child = measureChild (child); addViewInLayout (child, 0, child. getLayoutParams (), true); leftEdge-= child. getMeasuredWidth (); leftIndex --; // an important code is omitted here }}


This blog is designed to expand and modify the two core ideas to implement left-right scrolling. When moving left in version 2.0, you need to remove the View that meets certain conditions on the left at the right time (see the simple horizontal ListView implementation (version 2.0, when you want to scroll right, you also need to delete the View that exceeds the right screen from the Viewgroup (when child. getLeft () + the offset of moving is greater than parent. getWidth (): in short, you need to delete the invisible View on the left after scrolling to the left. When scrolling to the right, you need to delete the invisible View on the right after scrolling. The Code is as follows:


/* Delete invisible view */private void removeAnvisiableViews (int dianceX) {// remove the invisible view on the left. firtVisiableView = getChildAt (0); if (firtVisiableView! = Null & dianceX + firtVisiableView. getRight () <= 0) {removeViewInLayout (firtVisiableView); leftIndex ++; // an important line of code is omitted here} // you can remove the invisible view on the right. lastVisialbeView = getChildAt (getChildCount ()-1); if (lastVisialbeView! = Null & lastVisialbeView. getLeft () + dianceX> = getWidth () {removeViewInLayout (lastVisialbeView); rightIndex --;}}

So far, we have considered how to add the View on the left, when to add the View on the right, and when to delete the invisible View on both sides of the left and right under the conditions of left and right scrolling.. The rolling values of previous versions are all written to death. Now this version uses GestureDetector to handle finger movement. GestureDetector usage will not be described here. You can refer to many materials on the Internet. the SimpleOnGestureListener () contains an onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) method. Because it is horizontal scrolling, the third parameter distanceX is required, this parameter refers to the distance from the X-axis scroll when the onScroll method was called last time. So in the code, I used the variable distanceX to record it:

Public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// record the rolling distance of HListView. this. distanceX = (int) distanceX; // you still need to re-paint requestLayout (); return true ;};
Note that distanceX is greater than 0 when the finger is left, And distanceX is less than 0 when the finger is right. therefore, we need to reverse the method when using it, so we call this method in onLayout (this method was restructured before version 2.0 ):

@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {if (listAdapter == null) {return;}removeAnvisiableViews(-distanceX);addRightChildViews(-distanceX);addLeftChildViews(-distanceX);layoutChildViews(-distanceX);}
So far, I have basically said everything I should say. Run it and try it. I can't help it. What's the matter? All kinds of scratching your ears. At the end of the meal, the light flashed to know where the problem occurred! We know that the logic of horizontal listView scrolling is to repeat addView and removeView operations, but the most important thing is that the layoutChildViews method must be called for processing, in version2.0 code, the layoutChildViews code is like this:

Int childLeft = 0; for (int I = 0; I <getChildCount (); I ++) {View child = getChildAt (I); int childWidth = child. getMeasuredWidth (); child. layout (childLeft, 0, childWidth + childLeft, child. getMeasuredHeight (); // However, the best method is childLeft + = childWidth + child. getPaddingRight ();}

The first three parts of the layout method always start with 0 !!!! The problem lies here !!! Simply imagine how a half Item (or incomplete Item) on the left may start from 0 when rolling to the right, childLeft <0 will certainly occur. Therefore, when processing the first child View that can be seen on the left side, the first parameter of layout changes with scrolling, and it is not a fixed value of 0! In fact, I wrote in the above Code: an important line of code is omitted here. In fact, this line of code solves this problem!

I defined a leftOffset = 0 variable in the class to control the starting position of the next child View to be added (note that distanceX should be added ), (This variable is difficult to describe in language for a long time ). when the addleftChildView method is called, leftOffset-= child is performed on this variable every time a View is added. getMeasuredWidth ();. When a View on the left is deleted, leftOffset + = child. getMeasuredWidth (); so the layoutchildView code is changed:

Private void layoutChildViews (int distanceX) {if (getChildCount () = 0) {return;} leftOffset + = distanceX; int childLeft = leftOffset; for (int I = 0; I <getChildCount (); I ++) {View child = getChildAt (I); int childWidth = child. getMeasuredWidth (); child. layout (childLeft, 0, childWidth + childLeft, child. getMeasuredHeight (); // However, the best method is childLeft + = childWidth + child. getPaddingRight ();}}

Run one. OK! Version3.0 is now finished! However, the function is still incomplete. For example, if the first Item on the left is still available, you can scroll on the right, similarly, when the right side is the last View, it can still scroll to the left. Similarly, when the finger leaves, there is no inertial scroll. For example, every time you get the View, you need to parse the xml file, there is no good reuse of parsed xml and so on. These rich functions will be implemented in the next version. (Source code here)




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.