2012-02-27 12 views
6

アンドロイドのInstagramアプリのようにListViewのカスタムセクションまたはヘッダーを実装するにはどうすればよいですか? Android Listviewカスタムセクションヘッダー

http://prsarahevans.com/wp-content/uploads/2011/06/photo.PNG

は、ときにも残っていuserpic、名前と時間を持ち、他のヘッダーバーが近くに行くときにプッシュのようにそれをアニメーションバーをスクロールアップ。

ありがとうございます。

答えて

9

この問題は、リストビューでスクロールリスナーを使用することで解決できました。 (2.1でテスト済み)

各リスト行に対して、以下のようなレイアウトがあるとします。コンテンツ部分とヘッダー部分があります。ヘッダーやコンテンツに使用するビューの種類は関係ありません。

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" android:background="#FFFFFF"> 

    <ImageView 
     android:id="@+id/content" 
     android:layout_width="fill_parent" 
     android:layout_height="300dp" 
     android:scaleType="centerCrop" 
     android:src="@drawable/pic" 
     android:background="#aaaaff" 
     android:layout_marginTop="40dp"/> 

    <TextView 
     android:id="@+id/header" 
     android:layout_width="fill_parent" 
     android:layout_height="40dp" 
     android:padding="12dp" 
     android:text="Deneme Row" 
     android:textColor="#000000" 
     android:background="#99ffffff"/> 
</RelativeLayout> 

活性について試験レイアウトは、次のようになる:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 

    <ListView 
     android:id="@+id/list" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" > 
    </ListView> 
</LinearLayout> 

最後に活性のコードを以下に示します。ここでは、ViewHolderを使用してヘッダビューを格納するアダプタと、連続する各スクロールイベント(previousTop)のスクロールの変更を追跡する変数を持つアダプタを用意する必要がありました。これは、offsetTopAndBottom()が前の位置に関連するビューのオフセットを変更するためです。

public class TestActivity extends Activity implements AbsListView.OnScrollListener{ 

    ListView list; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     list = (ListView) findViewById(R.id.list); 
     list.setAdapter(new Adapter(this));   
     list.setOnScrollListener(this); 
    } 

    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem, 
      int visibleItemCount, int totalItemCount) {  
     //the listview has only few children (of course according to the height of each child) who are visible 
     for(int i=0; i < list.getChildCount(); i++){ 
      View child = list.getChildAt(i); 
      ViewHolder holder = (ViewHolder) child.getTag(); 

      //if the view is the first item at the top we will do some processing 
      if(i == 0){    
       boolean isAtBottom = child.getHeight() <= holder.header.getBottom(); 
       int offset = holder.previousTop - child.getTop(); 
       if(!(isAtBottom && offset > 0)){      
        holder.previousTop = child.getTop(); 
        holder.header.offsetTopAndBottom(offset);     
        holder.header.invalidate(); 
       } 
      } //if the view is not the first item it "may" need some correction because of view re-use 
      else if (holder.header.getTop() != 0) { 
       int offset = -1 * holder.header.getTop(); 
       holder.header.offsetTopAndBottom(offset); 
       holder.previousTop = 0; 
       holder.header.invalidate(); 
      } 
     } 
    } 

    @Override 
    public void onScrollStateChanged(AbsListView view, int scrollState) {} 

    private static class Adapter extends ArrayAdapter<String> { 
     public Adapter(Context context) { 
      super(context, R.layout.row, R.id.header); 
      for(int i=0; i < 50; i++){ 
       add(Integer.toString(i)); 
      } 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      if(convertView == null){ 
       convertView = LayoutInflater.from(getContext()).inflate(R.layout.row, parent, false); 
       ViewHolder holder = new ViewHolder(); 
       holder.header = (TextView) convertView.findViewById(R.id.header); 
       convertView.setTag(holder);    
      } 
      ViewHolder holder = (ViewHolder) convertView.getTag(); 
      holder.header.setText(getItem(position)); 
      return convertView; 
     } 
    } 

    private static class ViewHolder { 
     TextView header; 
     int previousTop = 0; 
    } 
} 
+0

siyamedねえ、 これは非常に便利です。 私の場合、ListView(親)内にもう1つリストビュー(子)があります。私がスクロールダウンしているときにヘッダーが正常に動作していません。 – ashish2py

+0

子リストビューにデータがない場合、正しく動作します。 >サンプルアプリケーション https://bitbucket.org/ashish2py/instagramheader – ashish2py

+0

私はそれを試みます。どうも! –

0

リストビューを使用している場合は、リストアイテム内に2つのビューがあります。 1つはヘッダーで、もう1つは実際にはアイテムです。

ヘッダービューを最初に非表示にし、スクロール状態の変更やユーザーがリスト項目に触れると、ヘッダーの表示が変更されます。

0

あなたのsetcontentviewの後に、以下のコードのようにしてください。

ListView list = getListView(); 
    View footer = getLayoutInflater().inflate(R.layout.footerlayout, list, false); 
    View header = getLayoutInflater().inflate(R.layout.headerlayout, list, false); 
    list.addHeaderView(header); 
    list.addFooterView(footer); 
1

ListView項目内のビットマップが変更された場合、ビューは、例えば再描画されるとき、ヘッダーが消えないように、私はSiyamedの質問を少し改善しました。

最後の位置に相対的な座標を使用するのではなく、ビューの先頭からの相対座標を使用し、オフセットの代わりにパディングを使用します。

@Override 
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

    for(int i=0; i < list.getChildCount(); i++){ 
     View child = list.getChildAt(i); 
     ViewHolder holder = (ViewHolder) child.getTag(); 

     if(i == 0){ 
      try { 
       boolean isAtBottom = child.getHeight() <= holder.movingHeader.getBottom(); 
       if(!(isAtBottom)){ 
        if (child.getTop() >= 0){} 
        else if (child.getHeight() - movingHeader.getHeight() - 1 > -child.getTop()) 
        { 
         holder.movingHeader.setPadding(0, -child.getTop(), 0, 0); 
         holder.movingHeader.invalidate(); 
        } 
        else { 
         holder.movingHeader.setPadding(0, child.getHeight() - movingHeader.getHeight(), 0, 0); 
         holder.movingHeader.invalidate(); 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       e.printStackTrace(); 
      } 
     } 
     else if (holder.movingHeader.getPaddingTop() != 0) 
     { 
      holder.movingHeader.setPadding(0, 0, 0, 0); 
      holder.movingHeader.invalidate(); 
     } 
    } 
} 
-1

私はこの質問は少し古いですけど、セクションヘッダの作成を抽象化するのはかなり良い仕事をしていませんStickyListHeadersライブラリを、見つけることができました。

https://github.com/emilsjolander/StickyListHeaders