2012-02-27 35 views

Trả lời

9

Tôi có thể giải quyết vấn đề này bằng cách sử dụng trình xử lý cuộn trên chế độ xem danh sách. (được thử nghiệm trên 2.1)

Cho phép nói cho mỗi hàng trong danh sách, tôi có bố cục như hình bên dưới. Có một phần nội dung và phần tiêu đề. Việc bạn sử dụng loại xem nào cho tiêu đề hoặc nội dung không quan trọng.

<?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> 

Cách bố trí thử nghiệm cho hoạt động này là như sau đây:

<?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> 

Cuối cùng mã cho hoạt động này được đưa ra dưới đây. Ở đây tôi đã có một bộ điều hợp sử dụng ViewHolder để lưu trữ chế độ xem tiêu đề và cũng là một biến để theo dõi thay đổi trong cuộn cho mỗi sự kiện cuộn liên tiếp (previousTop). Điều này là do thực tế offsetTopAndBottom() thay đổi độ lệch của khung nhìn liên quan đến vị trí trước đó của nó.

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

Hey siyamed, này là rất hữu ích. Trong trường hợp của tôi, tôi có thêm một ListView (con) bên trong ListView (Parent). do đó tiêu đề không hoạt động đúng khi tôi đang cuộn xuống .... – ashish2py

+0

Nếu không có dữ liệu trong chế độ xem danh sách trẻ em, thì nó hoạt động bình thường .. > ứng dụng mẫu https://bitbucket.org/ashish2py/instagramheader – ashish2py

+0

Tôi sẽ thử. Cám ơn! –

0

Nếu bạn đang sử dụng chế độ xem danh sách thì có 2 chế độ xem bên trong mục danh sách của bạn. Một là tiêu đề và khác thực sự là mục.

Ẩn chế độ xem đầu trang ban đầu và khi thay đổi trạng thái cuộn hoặc người dùng chạm vào mục danh sách của bạn sẽ thay đổi mức hiển thị của tiêu đề.

0

Sau khi setcontentview của bạn làm điều gì đó giống như mã bên dưới.

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

tôi đã cải thiện vấn đề Siyamed của một chút để các tiêu đề không phải là đi khi xem được vẽ lại ví dụ nếu một bitmap trong mục listview được thay đổi.

Thay vì sử dụng tọa độ tương ứng với vị trí cuối cùng, tôi sử dụng tọa độ tương ứng với phần trên cùng của chế độ xem và sử dụng phần đệm thay vì bù trừ.

@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(); 
     } 
    } 
}