2012-02-27 3 views
6

Как я могу реализовать пользовательский раздел или заголовок приложения ListView, такого как Instagram, в Android.Android Listview Пользовательский раздел Заголовок

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

При прокрутки вверх бар, которые имеют юзерпик, имя и время все еще будет там, и когда другой бар заголовка идти рядом с ним, то анимировать как толчок его.

Спасибо.

ответ

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 (дочерний элемент) внутри ListView (Parent). поэтому заголовок не работает должным образом, когда я прокручиваю-вниз .... – ashish2py

+0

Если в дочернем списке нет данных, тогда он работает правильно. > пример приложения https://bitbucket.org/ashish2py/instagramheader – ashish2py

+0

Я попробую. Спасибо! –

0

Если вы используете представление списка, у вас есть 2 вида внутри вашего элемента списка. Один - это заголовок, а другой - элемент.

Скрыть заголовок вначале и при изменении состояния прокрутки или касании пользователя элемент списка изменит видимость заголовка.

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

Я улучшил Question 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

Смежные вопросы