仿照微博详情页动态评论滚动头

最近做到一个需求,就是可以悬停的头部。就是当一个条目在屏幕之下的时候悬停在屏幕最下部,当条目在屏幕上方的时候,悬停在屏幕的头部。最终效果如下:
这里写图片描述
效果看起来不怎么好,因为mac上的GiF制作软件很奇怪,大家先看着吧。真的需要的话可以下载项目来运行试试。
首先我们考虑下实现的思路:
1.由于内容可滑动我们最好是放在listview 中。
2.由于listview的头部很大,可能超出屏幕,所以这个时候我们控件应该显示屏幕的最下方。
3.listview是有内容的,当内容很长的时候我们的头部是会被移动到屏幕的上面然后移除屏幕,此时我们需要将这个评论控件显示在屏幕的最上方。
好了这个就是具体的需求那我们怎么做呢:
1.我们可以重写listview的滑动事件,监听当评论的的头部滑到屏幕listview的头部时我们显示我们提前写好的一样的控件,这样用户看起来就是一个控件在使用。那么底部也是同理了。具体我们看代码:
activity代码:

package com.example.songzhihang.listheadtest;

import android.graphics.Rect;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;



public class MainActivity extends AppCompatActivity implements AbsListView.OnScrollListener {

    private static final String TAG = "MainActivity";

    int padding;
    TextView textview;
    private int statusBarHeight;
    private int contentTop;
    private int titleBarHeight;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.listview);

        listView.setAdapter(new MyAdapter());
        listView.setOnScrollListener(this);
        textview = (TextView) findViewById(R.id.text);
        padding=((View)(textview.getParent())).getPaddingTop()+  ((View)(textview.getParent())).getPaddingBottom();

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Rect frame = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        statusBarHeight = frame.top;  //状态栏高
        contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
        titleBarHeight = contentTop - statusBarHeight; //标题栏高
        Log.e(TAG, "statusBarHeight: "+statusBarHeight );
        Log.e(TAG, "contentTop: "+contentTop );
        Log.e(TAG, "titleBarHeight: "+titleBarHeight );
    }

    class MyAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return 20;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = new TextView(MainActivity.this);
                holder.view = (TextView) convertView;
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.view.setText("我是:" + position);
            holder.view.setTextSize(30);

            return convertView;
        }

        class ViewHolder {
            TextView view;
        }


    }

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

    }

/**
**重写滑动的方法
**/
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        View firstItem = view.getChildAt(0);
        textview = (TextView) MainActivity.this.findViewById(R.id.text);
        if (firstItem != null && firstItem instanceof LinearLayout) {
            Log.e(TAG, "firstItem.getY(): " + firstItem.getY());
            Log.e(TAG, "firstItem.getHeight(): " + firstItem.getHeight());
            Log.e(TAG, "view.getY(): " + view.getY());
            Log.e(TAG, "onScroll: " + ((LinearLayout) firstItem).getChildAt(1).getHeight());
            Log.e(TAG, "padding: " + padding);
            //当前控件的Y坐标(由于屏幕左上角是原点,那么屏幕都是负数)的负数大于等于到控件的高度的时候说明此事控件在屏幕中,那就影藏我们的备用控件,否则控件移除屏幕显示我们的备用控件
            // 由于我们的头部是个Linlayout,有2个子控件,所以我们的控件高度等于总高度减去第一个位置的控件高度
            if (-firstItem.getY() >= firstItem.getHeight() - ((LinearLayout) firstItem).getChildAt(1).getHeight()) {
                textview.setVisibility(View.VISIBLE);
            } else {
                textview.setVisibility(View.GONE);
            }
//通过屏幕的高度找到底部的位置,加上控件的高度,表明此事控件在最底部
//            if(getWinHeight()-view.getY()-padding-contentTop<=firstItem.getY()+firstItem.getHeight()){
            if(-firstItem.getY()<=680){
                findViewById(R.id.buttom_text).setVisibility(View.VISIBLE);
            }else{
                findViewById(R.id.buttom_text).setVisibility(View.GONE);
            }

        } else {
            textview.setVisibility(View.VISIBLE);
            findViewById(R.id.buttom_text).setVisibility(View.GONE);
        }


    }


    private int getWinHeight() {
        WindowManager wm = this.getWindowManager();
        int height = wm.getDefaultDisplay().getHeight();
        Log.e(TAG, "getWinHeight: "+height );
        return height;
    }

}

接下来看下布局文件:其中提前定义好的两个备用那个控件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.songzhihang.listheadtest.MainActivity">

    <View
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="#ff0"></View>


        <com.example.songzhihang.listheadtest.CusListView
            android:layout_below="@+id/view"
            android:id="@+id/listview"
            android:layout_width="match_parent"
            android:scrollbars="none"
            android:layout_height="match_parent"></com.example.songzhihang.listheadtest.CusListView>

    <TextView
        android:id="@+id/text"
        android:layout_below="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="我是头部"
        android:visibility="gone"
        android:background="#fff"
        />

    <TextView
        android:id="@+id/buttom_text"
        android:layout_alignParentBottom="true"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="我是头部"
        android:visibility="gone"
        android:background="#fff"
        />

</RelativeLayout>

然后看下自定的listview其中包含2个头部:

package com.example.songzhihang.listheadtest;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;

/**
 * @discription
 * @autor songzhihang
 * @time 2017/3/15  下午8:58
 **/
public class CusListView extends ListView{


    public CusListView(Context context) {
        super(context);
        init();
    }

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

    public CusListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

     void init(){

         LinearLayout headView=new LinearLayout(getContext());
         LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//         headView.setLayoutParams(params);
         headView.setOrientation(LinearLayout.VERTICAL);

         //内容布局
         View misshead=inflate(getContext(),R.layout.dismiss_head_layout,null);
         //长期驻存在屏幕的控件头
         View showhead=inflate(getContext(),R.layout.head_layout,null);

         headView.addView(misshead);
         headView.addView(showhead);
         addHeaderView(headView);

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(ev);
    }
}

其实这只是个思路,具体的话实现了我们可以做很多的事情,达到很多的效果。想看源码的同学可以看我的Github,地址:这里写链接内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值