Android Custom ScrollView ListView experience a variety of vertical sliding requirements

Source: Internet
Author: User

Reprint please indicate source: http://blog.csdn.net/lmj623565791/article/details/38950509, this article from "Zhang Hongyang's Blog"
1. Overview

One of the Buddies in the group. There is a need for this: the problem; The main function is: 1, a slide of the loop, 2, each sliding end, to maintain the integrity of each item. Then I wrote him a demo, all the code in the activity inside, later it seems too disgusting, modification is not convenient; Looks like that guy also because of that code changes to 12 points, greatly praise this friend's perseverance, also deeply apologized, today deliberately extracted code into a custom ScrollView , and then provide some callbacks out;

This blog first describes the use of custom ScrollView to solve the above problem, and then customize the ListView implementation to keep each item intact after each drag;

For transverse sliding, refer to:

Android Custom Horizontalscrollview Create more pictures (controls) also not afraid of the lateral sliding effect of OOM

Android Custom Recyclerview for true gallery effects

Horizontal and vertical very similar to Kazakhstan, a rewrite Horizontalscrollview, one is ScrollView, one to rewrite the ListView, one is Recyclerview, not much specific needs or discrepancies, if we have this aspect of demand can be used for reference. About horizontal have classmates ask how to ensure the sliding end to achieve a single item complete, you can refer to the portrait of the code today.

2, custom ScrollView implementation Loop Item drag

Now show the next, then explain the principle, the final analysis of the Code ~ Trilogy ~

1.:


2, the principle of realization

A, according to the user-provided adapter (mainly on two methods, GetCount "Decide how many item", GetView "the appearance of each item"), according to GetCount I will at the time of initialization, Add the corresponding number of item in ScrollView internal LinearLayout, of course, the screen height is equally divided according to the quantity;

B, monitoring Ontouch method, when the user triggers the Action_move, the screen follows the user's finger move, when the top is reached, will dynamically add an item to the top, while removing the bottom of the last item; The user slides to the bottom as well, adding an item to the bottom dynamically. Top first remove, ScrollView will always maintain the user specified number + 1 item, why add 1, because the drag process will show a maximum of 1 item (the first half, the last half)

c, monitoring action_up, judging if the display of course less than half, shrink back, more than half of the slowly show the full item;

3. Code Analysis

First we define a adapter that the user sets the appearance and number of items for each item; A ListView-like adapter

/** * Adapter * @author Zhy * */public static abstract class Adapter{public abstract View GetView (singleitemscrollview parent, int pos);p ublic abstract int getcount ();}

Get the height of the screen in the construction method

Public Singleitemscrollview (context context, AttributeSet Attrs) {Super (context, attrs);//Calculate the height of the screen windowmanager wm = ( WindowManager) Context.getsystemservice (context.window_service);D isplaymetrics outmetrics = new DisplayMetrics (); Wm.getdefaultdisplay (). Getmetrics (outmetrics); mscreenheight = outmetrics.heightpixels;mscreenheight-= Getstatusheight (context);}

Add the item in Onmeasure, and set the height

@Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//prevents multiple calls to if (!flag) {Mcontainer = ( ViewGroup) getchildat (0);//Based on adapter method, add itemif (madapter! = null) {Mitemcount = Madapter.getcount () for the container; mitemheight = Mscreenheight/mitemcount;mcontainer.removeallviews (); for (int i = 0; i < Madapter.getcount (); i++) {Addchildview (i);} }addchildview (0);} Super.onmeasure (Widthmeasurespec, heightmeasurespec);} /** * Add an item at the end of the container * @param i */private void addchildview (int i) {View item = Madapter.getview (this, i);//Set parameter Android.view . Viewgroup.layoutparams LP = new Viewgroup.layoutparams (Android.view.ViewGroup.LayoutParams.MATCH_PARENT, Mitemheight); item.setlayoutparams (LP);//Set Tagitem.settag (i);//Add Event Item.setonclicklistener (this); Mcontainer.addview (item);}

Next is the carbon ontouchevent.

@Overridepublic boolean ontouchevent (motionevent ev) {flag = True;int action = ev.getaction (); int scrolly = Getscrolly (); s Witch (Action) {case MOTIONEVENT.ACTION_MOVE:LOG.E ("TAG", "scrolly =" + scrolly),//means that at this point the top of the ScrollView has reached the top of the screen if ( Scrolly = = 0) {Addchildtofirst ();} The top of the ScrollView has reached the bottom of the screen if (Math.Abs (scrolly-mitemheight) <= mitemcount) {addchildtolast ();} Break;case MotionEvent.ACTION_UP:checkForReset (); return true;default:break;} return super.ontouchevent (EV);} /** * Adds a view at the bottom and removes the first view */private void Addchildtolast () {LOG.E ("TAG", "addchildtolast"); int pos = (Integer) Mcontainer.getchildat (1). Gettag (); Addchildview (POS); Mcontainer.removeviewat (0); This.scrollto (0, 0);} /** * Add a view at the top and remove the last view */protected void Addchildtofirst () {LOG.E ("TAG", "Addchildtofirst"); int pos = (Integer) Mcontainer.getchildat (mItemCount-1). Gettag () Addchildview (POS, 0); Mcontainer.removeviewat ( Mcontainer.getchildcount ()-1); This.scrollto (0, mitemheight);} /** * Check current getscrolly, show complete item, or shrink this item */private void Checkforreset () {int val = getscrolly ()% mitemheight;if (val >= mitemheight/2) {smoothscrollto (0, Mitemheight );} Else{smoothscrollto (0, 0);}}
You can see in the action_move we only judge whether to reach the top or bottom;

if (Math.Abs (scrolly-mitemheight) <= mitemcount) Such a judgment, mainly because, worried about the number of users set to take the height of the screen is not evenly divisible, integer in addition to the integer inevitably have a rounding something, So I set a small range;

When we get to the top, there is no item at the top, so we add an item to the top and remove the last one at the bottom, and we need to move the scrolly to the place where it was not added, to give the user a seamless experience;

At the bottom of the same ~

When action_up, we check the current scrolly, if the item height is less than half of the height of item, less than half of the height of item means that the hidden part is less than normal, and the display part is more than half, So we smoothscrollto (0, 0), display the complete item, or vice versa;


The value obtained after the remainder is actually beyond the screen part, that is, the hidden part, if it is greater than half, then the display part is less than half;

Use of users in mainactivity

Package Com.example.zhy_wangandroid_hownoon;import Java.util.arraylist;import Java.util.arrays;import Java.util.list;import Android.app.activity;import Android.graphics.color;import Android.os.Bundle;import Android.view.layoutinflater;import Android.view.view;import Android.view.window;import Android.widget.ImageView; Import Android.widget.toast;import Com.example.zhy_wangandroid_hownoon. Singleitemscrollview.adapter;import Com.example.zhy_wangandroid_hownoon. Singleitemscrollview.onitemclicklistener;public class Mainactivity extends Activity{private SingleItemScrollView Mscrollview;private Adapter madapter;private layoutinflater minflater;private list<bean> mDatas = new ArrayList <Bean> (//new bean (r.drawable.icon_about, Color.rgb (123, Arrays.aslist)),//new Bean (r.drawable.icon_map , Color.rgb (145),//new bean (r.drawable.icon_message, COLOR.RGB (177, 234, 145)),//new Bean (r.drawable.icon_oil , Color.rgb (134, 145)); @Overrideprotected void OnCreate (Bundle saveDinstancestate) {super.oncreate (savedinstancestate); Requestwindowfeature (Window.feature_no_title); Setcontentview (r.layout.activity_main); minflater = Layoutinflater.from (this); Mscrollview = (SingleItemScrollView) Findviewbyid (r.id.id_scrollview); madapter = new Adapter () {@Overridepublic View GetView (singleitemscrollview parent, int pos) {View view = Minflater.inflate (R.layout.item, null); ImageView IV = (ImageView) View.findviewbyid (r.id.id_title) ; Iv.setimageresource (Mdatas.get (POS). Getresid ()); View.setbackgroundcolor (Mdatas.get (POS). GetColor ()); return View;} @Overridepublic int GetCount () {return 4;}}; Mscrollview.setadapter (Madapter); Mscrollview.setonitemclicklistener (new Onitemclicklistener () {@Overridepublic void Onitemclick (int pos, view view) {Toast.maketext (Getapplicationcontext (), pos + "", Toast.length_short). Show ();}});}}

The user gets the control, sets the adapter, sets the data in the GetView, and determines the appearance of the item; provides a setonitemclicklistener callback for the user to set the processing of each item by clicking on it; the usage style of the ListView is basically consistent ;

4. layout file

Main layout file:

<scrollview xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    android:id=" @+id/id_scrollview "    android:scrollbars=" None "    android: Layout_width= "Fill_parent"    android:layout_height= "wrap_content" >    <linearlayout        android:id= "@ +id/id_container "        android:layout_width=" fill_parent "        android:layout_height=" Wrap_content "        Android : orientation= "Vertical" >    </LinearLayout></ScrollView>

The layout of the item

<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "    android:layout_width=" match_parent "    android:layout_height=" Match_parent "    android: Background= "#000000"    android:gravity= "center" >    <imageview        android:id= "@+id/id_title"        Android:layout_width= "Fill_parent"        android:layout_height= "wrap_content"        android:scaletype= "FitCenter"        android:src= "@drawable/icon_about"/></linearlayout>


3, custom listview use sliding end full display Item1,:


2. Principle of realization

First Analyze:

If you want to end the display complete, then there is a premise that your item should have a fixed number of full item when initializing a screen;

This requires a parameter to specify how many item to display on a screen, and a height for each item based on the item number;

There is a problem, the item layout is set in adapter, that is, we have to set this height in the GetView, but this height is actually calculated in the ListView, so the external release of this height;

In the end, it is the monitoring scroll to determine whether the current display is complete, if so, if not;

3. Implementation code

A. Custom properties

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <attr name= "ItemCount" format= "integer"/>    <declare-styleable name= "Mylistview" >        <attr name= "ItemCount"/>    </declare-styleable ></resources>

It's simply a property;

B, layout file:

<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    xmlns:zhy=" http://schemas.android.com/apk/res/com.example.zhy_wangandroid_ Hownoon "    android:id=" @+id/id_scrollview "    android:layout_width=" fill_parent "    android:layout_height= "Fill_parent"    android:orientation= "vertical" >    <com.example.zhy_wangandroid_hownoon. Mylistview        android:id= "@+id/id_lv"        android:layout_width= "fill_parent" android:layout_height= "Wrap_        Content "        android:divider=" @null "        zhy:itemcount=" 8 ">    </com.example.zhy_wangandroid_hownoon . Mylistview></linearlayout>

C, Mylistview

Package Com.example.zhy_wangandroid_hownoon;import Android.content.context;import Android.content.res.TypedArray; Import Android.util.attributeset;import Android.util.displaymetrics;import Android.util.log;import Android.view.windowmanager;import Android.widget.abslistview;import Android.widget.AbsListView.OnScrollListener; Import Android.widget.listview;public class Mylistview extends ListView implements onscrolllistener{private static Final String TAG = MyListView.class.getSimpleName ();/** * Each screen shows how many item */private int mitemcountinonescreen;/** * Each item's Height */private int mitemheight;/** * Records the first displayed item */private int mfirstvisibleitem;public Mylistview (context context, Attrib Uteset attrs) {This (context, attrs, 0);} /** * Construction method Get custom attribute ItemCount, calculate each item height * @param context * @param attrs * @param defstyle */public mylistview (Context Conte XT, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle); WindowManager wm = (WindowManager) context.getsystemservice (context.window_service);D isPlaymetrics outmetrics = new Displaymetrics (); Wm.getdefaultdisplay (). Getmetrics (outmetrics);//Get Mylistview_ Itemcounttypedarray a = Context.gettheme (). Obtainstyledattributes (Attrs,r.styleable.mylistview, DefStyle, 0); int n = A.getindexcount (); for (int i = 0, i < n; i++) {int attr = A.getindex (i); switch (attr) {case R.styleable.mylistview_itemco Unt:mitemcountinonescreen = A.getint (attr, 6); break;}} A.recycle ();//Calculate each item height Mitemheight = (outmetrics.heightpixels-getstatusheight (context))/mitemcountinonescreen;/ /Set a scrolling monitor setonscrolllistener (this); LOG.E (TAG, Mitemcountinonescreen + "");} @Overridepublic void onscrollstatechanged (abslistview view, int scrollstate) {//scroll End if (scrollstate = = Onscrolllistener.scroll_state_idle) {//LOG.E (TAG, Getchildat (0). GetTop () + "GetTop ()"); LOG.E (TAG, Mfirstvisibleitem + "Scroll_state_idle");//Gets the Topint top = getchildat (0) of the first item. GETTOP (); if (top = = 0) return ;//absolute value is not 0 o'clock, if the absolute value is greater than half of Mitemheight, then the next itemif (Math.Abs (top) > MITEMHEIGHT/2) {This.setselection (Mfirstvisibleitem + 1);//This.scrollto (x, y)//Smoothscrolltoposition (MFIRSTVISIBLEITEM-1);//Scrollby (0, Mitemheight-math.abs (top));//Smoothscrollby (Mitemheight-math.abs (top), 200);} else//absolute value is not 0 o'clock, if the absolute is less than half of mitemheight, then expands to show the current full item{this.setselection (Mfirstvisibleitem);//This.scrollto (x, y) Smoothscrollby (top),-math.abs,//Smoothscrollbyoffset (offset);//Scrollby (0,-math.abs (top));// Smoothscrolltoposition (Mfirstvisibleitem);} Smoothscrolltoposition (Mfirstvisibleitem);}} /** * Keep track of the first item that is currently displayed */@Overridepublic void onscroll (abslistview view, int firstvisibleitem,int visibleitemcount) during scrolling , int totalitemcount) {Mfirstvisibleitem = firstvisibleitem;//log.e (TAG, Mfirstvisibleitem + "");} /** * Publish the height of each item * @return */public int getitemheight () {return mitemheight;} /** * Get the height of the status bar * * @param context * @return */public int Getstatusheight (context context) {int statusheight = -1;try{class <?> clazz = Class.forName ("Com.android.internal.r$dimen"); object object = Clazz.newinstance (); int height = Integer.parseint (Clazz.getfield ("Status_bar_height"). Get (object). toString ()); Statusheight = Context.getresources (). getdimensionpixelsize (height);} catch (Exception e) {e.printstacktrace ();} return statusheight;}}

Code is relatively small, but also relatively simple, we can focus on, I onscrollstatechanged commented out of those methods, in principle, each should be able to achieve, but I finally chose SetSelection (Mfirstvisibleitem); If you are interested, try another method.

D, in Mainactivity

Package Com.example.zhy_wangandroid_hownoon;import Java.util.arraylist;import Java.util.list;import Java.util.random;import Com.zhy.utils.commonadapter;import Com.zhy.utils.viewholder;import android.app.Activity; Import Android.graphics.color;import android.os.bundle;import android.view.view;import android.view.ViewGroup; Import Android.view.window;public class Mainactivity extends Activity{private mylistview mlistview;private commonadapter<string> madapter;private list<string> mdatas; @Overrideprotected void OnCreate (Bundle Savedinstancestate) {super.oncreate (savedinstancestate); Requestwindowfeature (Window.feature_no_title); Setcontentview (r.layout.activity_main); Mlistview = (Mylistview) Findviewbyid (R.ID.ID_LV); InitDatas (); InitViews ();} private void Initviews () {Mlistview = (Mylistview) Findviewbyid (R.ID.ID_LV); madapter = new Commonadapter<string> ( This, Mdatas, r.layout.item) {@Overridepublic void convert (Viewholder helper, String item) {View Convertview = Helper.getconvertvIew (); Convertview.setbackgroundcolor (Color.rgb (New Random () Nextint (255), New Random (). Nextint (255), New Random (). Nextint (255))); Viewgroup.layoutparams LP = Convertview.getlayoutparams (); lp.height = Mlistview.getitemheight (); CONVERTVIEW.SETLAYOUTPARAMS (LP); Helper.settext (R.id.id_title, item);}}; Mlistview.setadapter (Madapter);} private void Initdatas () {Mdatas = new arraylist<string> (); for (int i = ' A '; I <= ' Z '; i++) {Mdatas.add (String.valu EOf ((char) +i));}}}

The use is not to say, I used our previous package of commonadapter, if not understand can refer to:Android Rapid Development series to create a universal ListView GridView adapter; If you don't like to change to the traditional adapter, I believe you should have no problem ~

There are also some requirements to meet each stop display complete item, but also hope that even if the user gave an acceleration, when the user lifted the finger, will not automatically scroll;

4. ListView Display Full item, screen Auto scroll

This is easier, only need to copy the Ontouchevent method, and then after Action_up, the check is to show/shadow the current item, and then return true;

@Overridepublic boolean ontouchevent (motionevent ev) {int action = ev.getaction (); if (action = = motionevent.action_up) { Checkforreset (); return true;} return super.ontouchevent (EV);} @Overridepublic void onscrollstatechanged (abslistview view, int scrollstate) {//scroll End if (scrollstate = = Onscrolllistener.scroll_state_idle) {checkforreset ();}}
The key code as above, all other code and the above example is consistent;
:




Okay, here's the introduction.


SOURCE Click to download



Android Custom ScrollView ListView experience a variety of vertical sliding requirements

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.