亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android-section-list分組列表

系統(tǒng) 1861 0

分組列表項目源碼地址:

http://code.google.com/p/android-section-list/

android中l(wèi)istiew仿組向上滾動特效 原文地址:

http://www.cnblogs.com/xiaoQLu/archive/2011/12/20/2293732.html


非常感謝 kylin17 喲一嗨 同學(xué)發(fā)現(xiàn)的bug,確實存在此問題,已修正

MySectionIndexer.java中 public int getPositionForSection( int section)方法第一個判斷有誤,應(yīng)該為大于等于,已修改,源碼重新上傳

手機qq上有這樣一個特效:當(dāng)前分組的好友,向上滾動時,在頂部會出現(xiàn)一個透明的框,當(dāng)下一個分組到達(dá)時,會把上一個分組慢慢頂上去,覺得這個特效蠻有意思,就研究了一下,android自帶的通訊錄分組就有這個特效,這里是自己仿寫的一個,部分源碼從通訊錄中扣出來的

實現(xiàn)原理:

前提條件,假設(shè)所有的數(shù)據(jù)已經(jīng)分好組

1.listview中每一個item都默認(rèn)有一個分組標(biāo)簽,但是只顯示此分組下面的第一個,其他的默認(rèn)不顯示

2.滾動的時候,判斷每一個分組的狀態(tài),是向上滾動,還是完全顯示,或者隱藏,主要是取當(dāng)前item所在的分組跟(下一個分組-1=當(dāng)前分組)相比,如果相等,說明是向上流動,否則是隱藏

3.獲取當(dāng)前分組的狀態(tài)后,就可以放置分組的位置了,這里使用view.layout(int left,int top,int rigth,int bottom) ,其他left是0,right是分組標(biāo)簽的長度,top和bottom是需要計算的,用ViewGroup.getChileAt(0)獲取listview中第一個孩子的view,然后用bottom=view.getBottom獲取底部距離父窗口的位置,最后得到兩者之差y=bottom-標(biāo)題框的高度,用這個差就可以得出頂部和底部的位置,就是top和bottom的值。

關(guān)鍵類解析

PinnedHeaderListView.java 這個是實現(xiàn)listview分組的關(guān)鍵,當(dāng)然布局文件中的listview也要使用這個類,里面有個接口,adapter要實現(xiàn)此接口,是滾動時回調(diào)用,其中g(shù)etPinnedHeaderState()是用來分組標(biāo)簽狀態(tài)的,

它的3種狀態(tài)都在此接口中定義,configurePinnedHeader()是用來設(shè)置分組標(biāo)簽的標(biāo)題,也是相當(dāng)于組中的組名,此類中的configHeaderView()就是放置分組使用的,結(jié)合上面的分析跟這個方法研究這個類

        
          /*
        
        
          
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      
        
        
          http://www.apache.org/licenses/LICENSE-2.0
        
        
          
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 
        
        
          */
        
        
          package
        
         com.demo.sectionlistview;


        
          import
        
         android.content.Context;

        
          import
        
         android.graphics.Canvas;

        
          import
        
         android.util.AttributeSet;

        
          import
        
         android.view.View;

        
          import
        
         android.widget.ListAdapter;

        
          import
        
         android.widget.ListView;


        
          /**
        
        
          
 * A ListView that maintains a header pinned at the top of the list. The
 * pinned header can be pushed up and dissolved as needed.
 
        
        
          */
        
        
          public
        
        
          class
        
         PinnedHeaderListView 
        
          extends
        
         ListView {

    
        
          /**
        
        
          
     * Adapter interface.  The list adapter must implement this interface.
     
        
        
          */
        
        
          public
        
        
          interface
        
         PinnedHeaderAdapter {

        
        
          /**
        
        
          
         * Pinned header state: don't show the header.
         
        
        
          */
        
        
          public
        
        
          static
        
        
          final
        
        
          int
        
         PINNED_HEADER_GONE = 0;

        
        
          /**
        
        
          
         * Pinned header state: show the header at the top of the list.
         
        
        
          */
        
        
          public
        
        
          static
        
        
          final
        
        
          int
        
         PINNED_HEADER_VISIBLE = 1;

        
        
          /**
        
        
          
         * Pinned header state: show the header. If the header extends beyond
         * the bottom of the first shown element, push it up and clip.
         
        
        
          */
        
        
          public
        
        
          static
        
        
          final
        
        
          int
        
         PINNED_HEADER_PUSHED_UP = 2;

        
        
          /**
        
        
          
         * Computes the desired state of the pinned header for the given
         * position of the first visible list item. Allowed return values are
         * {
        
        
          @link
        
        
           #PINNED_HEADER_GONE}, {
        
        
          @link
        
        
           #PINNED_HEADER_VISIBLE} or
         * {
        
        
          @link
        
        
           #PINNED_HEADER_PUSHED_UP}.
         
        
        
          */
        
        
          int
        
         getPinnedHeaderState(
        
          int
        
         position);

        
        
          /**
        
        
          
         * Configures the pinned header view to match the first visible list item.
         *
         * 
        
        
          @param
        
        
           header pinned header view.
         * 
        
        
          @param
        
        
           position position of the first visible list item.
         * 
        
        
          @param
        
        
           alpha fading of the header view, between 0 and 255.
         
        
        
          */
        
        
          void
        
         configurePinnedHeader(View header, 
        
          int
        
         position, 
        
          int
        
         alpha);
    }

    
        
          private
        
        
          static
        
        
          final
        
        
          int
        
         MAX_ALPHA = 255;

    
        
          private
        
         PinnedHeaderAdapter mAdapter;
    
        
          private
        
         View mHeaderView;
    
        
          private
        
        
          boolean
        
         mHeaderViewVisible;

    
        
          private
        
        
          int
        
         mHeaderViewWidth;

    
        
          private
        
        
          int
        
         mHeaderViewHeight;

    
        
          public
        
         PinnedHeaderListView(Context context) {
        
        
          super
        
        (context);
    }

    
        
          public
        
         PinnedHeaderListView(Context context, AttributeSet attrs) {
        
        
          super
        
        (context, attrs);
    }

    
        
          public
        
         PinnedHeaderListView(Context context, AttributeSet attrs, 
        
          int
        
         defStyle) {
        
        
          super
        
        (context, attrs, defStyle);
    }

    
        
          public
        
        
          void
        
         setPinnedHeaderView(View view) {
        mHeaderView = view;

        
        
          //
        
        
           Disable vertical fading when the pinned header is present
        
        
        
          //
        
        
           TODO change ListView to allow separate measures for top and bottom fading edge;
        
        
        
          //
        
        
           in this particular case we would like to disable the top, but not the bottom edge.
        
        
        
        
          if
        
         (mHeaderView != 
        
          null
        
        ) {
            setFadingEdgeLength(0);
        }
        requestLayout();
    }

    @Override
    
        
          public
        
        
          void
        
         setAdapter(ListAdapter adapter) {
        
        
          super
        
        .setAdapter(adapter);
        mAdapter = (PinnedHeaderAdapter)adapter;
    }

    @Override
    
        
          protected
        
        
          void
        
         onMeasure(
        
          int
        
         widthMeasureSpec, 
        
          int
        
         heightMeasureSpec) {
        
        
          super
        
        .onMeasure(widthMeasureSpec, heightMeasureSpec);
        
        
          if
        
         (mHeaderView != 
        
          null
        
        ) {
            measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
            mHeaderViewWidth = mHeaderView.getMeasuredWidth();
            mHeaderViewHeight = mHeaderView.getMeasuredHeight();
        }
    }

    @Override
    
        
          protected
        
        
          void
        
         onLayout(
        
          boolean
        
         changed, 
        
          int
        
         left, 
        
          int
        
         top, 
        
          int
        
         right, 
        
          int
        
         bottom) {
        
        
          super
        
        .onLayout(changed, left, top, right, bottom);
        
        
          if
        
         (mHeaderView != 
        
          null
        
        ) {
            mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
            configureHeaderView(getFirstVisiblePosition());
        }
    }

    
        
          public
        
        
          void
        
         configureHeaderView(
        
          int
        
         position) {
        
        
          if
        
         (mHeaderView == 
        
          null
        
        ) {
            
        
          return
        
        ;
        }

        
        
          int
        
         state = mAdapter.getPinnedHeaderState(position);
        
        
          switch
        
         (state) {
            
        
          case
        
         PinnedHeaderAdapter.PINNED_HEADER_GONE: {
                mHeaderViewVisible = 
        
          false
        
        ;
                
        
          break
        
        ;
            }

            
        
          case
        
         PinnedHeaderAdapter.PINNED_HEADER_VISIBLE: {
                mAdapter.configurePinnedHeader(mHeaderView, position, MAX_ALPHA);
                
        
          if
        
         (mHeaderView.getTop() != 0) {
                    mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
                }
                mHeaderViewVisible = 
        
          true
        
        ;
                
        
          break
        
        ;
            }

            
        
          case
        
         PinnedHeaderAdapter.PINNED_HEADER_PUSHED_UP: {
                View firstView = getChildAt(0);
                
        
          int
        
         bottom = firstView.getBottom();

        
          //
        
        
                          int itemHeight = firstView.getHeight();
        
        
        
        
          int
        
         headerHeight = mHeaderView.getHeight();
                
        
          int
        
         y;
                
        
          int
        
         alpha;
                
        
          if
        
         (bottom < headerHeight) {
                    y = (bottom - headerHeight);
                    alpha = MAX_ALPHA * (headerHeight + y) / headerHeight;
                } 
        
          else
        
         {
                    y = 0;
                    alpha = MAX_ALPHA;
                }
                mAdapter.configurePinnedHeader(mHeaderView, position, alpha);
                
        
          if
        
         (mHeaderView.getTop() != y) {
                    mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);
                }
                mHeaderViewVisible = 
        
          true
        
        ;
                
        
          break
        
        ;
            }
        }
    }

    @Override
    
        
          protected
        
        
          void
        
         dispatchDraw(Canvas canvas) {
        
        
          super
        
        .dispatchDraw(canvas);
        
        
          if
        
         (mHeaderViewVisible) {
            drawChild(canvas, mHeaderView, getDrawingTime());
        }
    }
}
      


MySectionIndexer.java類,主要是用來提供分組的數(shù)據(jù)的,主要包括,String[]mSections-->所有的組名,int[] mPositions-->每一個組名在listivew中的位置,當(dāng)然,他們的長度應(yīng)該是相同的。

        
          package
        
        
           com.demo.sectionlistview;


        
        
          import
        
        
           java.util.Arrays;


        
        
          import
        
        
           android.widget.SectionIndexer;


        
        
          public
        
        
          class
        
         MySectionIndexer 
        
          implements
        
        
           SectionIndexer{
    
        
        
          private
        
        
          final
        
         String[] mSections;
        
          //

        
        
          private
        
        
          final
        
        
          int
        
        
          [] mPositions;
    
        
        
          private
        
        
          final
        
        
          int
        
        
           mCount;
    
    
        
        
          /**
        
        
          
     * 
        
        
          @param
        
        
           sections
     * 
        
        
          @param
        
        
           counts
     
        
        
          */
        
        
          public
        
         MySectionIndexer(String[] sections, 
        
          int
        
        
          [] counts) {
        
        
        
          if
        
         (sections == 
        
          null
        
         || counts == 
        
          null
        
        
          ) {
            
        
        
          throw
        
        
          new
        
        
           NullPointerException();
        }
        
        
        
          if
        
         (sections.length !=
        
           counts.length) {
            
        
        
          throw
        
        
          new
        
        
           IllegalArgumentException(
                    
        
        "The sections and counts arrays must have the same length"
        
          );
        }
        
        
        
          this
        
        .mSections =
        
           sections;
        mPositions 
        
        = 
        
          new
        
        
          int
        
        
          [counts.length];
        
        
        
          int
        
         position = 0
        
          ;
        
        
        
          for
        
         (
        
          int
        
         i = 0; i < counts.length; i++
        
          ) {
            
        
        
          if
        
        (mSections[i] == 
        
          null
        
        
          ) {
                mSections[i] 
        
        = ""
        
          ;
            } 
        
        
          else
        
        
           {
                mSections[i] 
        
        =
        
           mSections[i].trim(); 
            }
            
            mPositions[i] 
        
        =
        
           position;
            position 
        
        +=
        
           counts[i];
        }
        mCount 
        
        =
        
           position;
    }
    
    @Override
    
        
        
          public
        
        
           Object[] getSections() {
        
        
        
          //
        
        
           TODO Auto-generated method stub
        
        
          return
        
        
           mSections;
    }

    @Override
    
        
        
          public
        
        
          int
        
         getPositionForSection(
        
          int
        
        
           section) {
        
        
        
          //
        
        
          change by lcq 2012-10-12 section > mSections.length以為>= 
        
        
          if
        
         (section < 0 || section >=
        
           mSections.length) {
            
        
        
          return
        
         -1
        
          ;
        }
System.out.println(
        
        "lcq:section:"+
        
          section);
        
        
        
          return
        
        
           mPositions[section];
    }

    @Override
    
        
        
          public
        
        
          int
        
         getSectionForPosition(
        
          int
        
        
           position) {
        
        
        
          if
        
         (position < 0 || position >=
        
           mCount) {
            
        
        
          return
        
         -1
        
          ;
        }
        
        
        
          //
        
        
          注意這個方法的返回值,它就是index<0時,返回-index-2的原因
        
        
        
          //
        
        
          解釋Arrays.binarySearch,如果搜索結(jié)果在數(shù)組中,剛返回它在數(shù)組中的索引,如果不在,剛返回第一個比它大的索引的負(fù)數(shù)-1
        
        
        
          //
        
        
          如果沒弄明白,請自己想查看api
        
        
          int
        
         index =
        
           Arrays.binarySearch(mPositions, position);
        
        
        
          return
        
         index >= 0 ? index : -index - 2; 
        
          //
        
        
          當(dāng)index小于0時,返回-index-2,
        
        
                  
    }

}
        
      

  當(dāng)然,adapter也灰常重要,這里簡單分析下,因為具體使用時,會根據(jù)情況使用不同的adapter,比如說,有數(shù)據(jù)庫的,可以使用SimpleCursorAdapter,也可以使用SimpleAdapter等等,這里使用的原始的listAdapter,比較麻煩,這里要實現(xiàn)上面提到的PinnedHeaderAdapter,還要實現(xiàn)SectionIndexer,主要是用來根據(jù)實際位置查找分組的索引,以及根據(jù)索引返回組名在實際listview中的位置(這里有點不太好講,不太懂的,仔細(xì)看源碼和api)

其他的就是一些adapter的基本應(yīng)用以及一些android 的基本知識,這里不在講述,不懂的請?zhí)釂枴?

源碼下載地址:http://files.cnblogs.com/xiaoQLu/DemoSectionListView_Plus.rar



Android-section-list分組列表


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧美激情免费观看一区 | 免费人成年短视频在线观看网站 | 欧美中文字幕在线看 | 国产精品456 | 久久综合给会久久狠狠狠 | 九九精品免视看国产成人 | 高清国产一级毛片国语 | 久草在线观看首页 | 亚洲精品成人a在线观看 | 国产欧美日韩中文久久 | 一男一女一级毛片 | 国产女人水多毛片18 | 在线免费观看一区二区三区 | 波多野结衣免费一区二区三区香蕉 | 福利在线网站 | 毛片免费全部播放一级 | 日本特级aⅴ一级毛片 | 四虎4444hu4影视最新地址 | 久久99国产精品视频 | 日本色综合 | 98在线视频噜噜噜国产 | 欧美一区二区三区精品国产 | 色综合久久中文字幕 | 精品一区 二区三区免费毛片 | 四虎永久在线精品视频免费观看 | 国产色综合久久无码有码 | 福利在线影院 | 老头做爰xxxx视频 | 成人性生免费视频 | 日本aⅴ在线不卡免费观看 日本aaaa | 日韩毛片在线免费观看 | 亚洲视频网 | 亚洲好视频 | 狠狠色很很在鲁视频 | 久久婷婷是五月综合色狠狠 | 成人私人影院在线观看网址 | 综合伊人久久在一二三区 | 宅男噜噜噜66一区二区 | 奇米第七色 | 四虎四虎1515hhcom| 99人中文字幕亚洲区 |