Android的列表视图自定义栏目标题自定义、视图、栏目、标题

2023-09-06 00:18:28 作者:时间怂恿深爱的人放手

我怎样才能实现自定义部分或ListView像机器人的Instagram应用程序的标题。

How can i implement custom section or header of ListView like Instagram app in android.

https://m.xsw88.com/allimgs/daicuo/20230906/273.png

在向上滚动有userpic,名称和时间依然存在,当其他标题栏去接近它,然后像动画推起来了吧。

When scroll up the bar that have userpic, name and time still be there and when other header bar go near it then animate like push it up.

感谢你。

推荐答案

我能够通过使用滚动监听器的列表视图来解决这个问题。 (在2.1测试)

I was able to solve this issue by using scroll listener on the listview. (tested on 2.1)

可以说,每个列表行我有一个类似下面的布局。有一个内容部分和报头部分。这不要紧,你使用的标题或内容是什么视图类型。

Lets say for each list row I have a layout like the one below. There is a content part and a header part. It doesn't matter what view type you use for header or content.

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

该活动的测试内容编排如下所示:

The test layout for the activity is as in the following:

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

最后,code代表的活性如下。这里我必须有它使用ViewHolder来存储头部视图,并且也是变量来跟踪变化的在滚动对于每个连续滚动事件(previousTop)的适配器。这是因为这一事实,即offsetTopAndBottom()的变化有关的它的previous位置的视图偏移。

Finally the code for the activity is given below. Here I had to have an adapter which uses ViewHolder to store the header view and also a variable to keep track of the change in the scroll for each successive scroll events (previousTop). This is because of the fact that offsetTopAndBottom() changes offset of the view related to the previous location of it.

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;
    }
}