代码仅为个人笔记,勿喷


关键代码:

----------------------------------------------------------------------------------------------------------------------------------------------------------

1.设置滑动监听


private void setListener() {
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView listView, final int state) {
                    listView.setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                            int action = event.getAction();
                            switch (action) {
                                case MotionEvent.ACTION_CANCEL:
                                case MotionEvent.ACTION_UP:
//                                    Log.e(TAG,"ACTION_UP");
                                    isFirst = true;
                                    //抬起手指之后
                                    if(isShow){
                                        if(height > Float.valueOf(0.5f*density).intValue() ){//控件高度大于一定高度时,显示全部控件
                                            showHeader(headerLayout,Float.valueOf(99 * density).intValue(),Float.valueOf(1*density).intValue());
                                        }
                                        isShow = false;
                                    }

                                    if(isHide){
                                        if(height < Float.valueOf(99*density).intValue() ){//控件高度小于一定高度时,隐藏全部控件
                                            hideHeader(headerLayout,Float.valueOf(1 * density).intValue(),Float.valueOf(1*density).intValue());
                                        }
                                        isHide = false;
                                    }
                                    break;
                                case MotionEvent.ACTION_MOVE:
                                    if(isFirst){//记录第一次按下时的y坐标
                                        downY = event.getY();
                                        isFirst = false;
                                    }
                                    moveY = event.getY();
                                    float dur = moveY - downY;
                                    float temp = Math.abs(dur);
                                    if(temp > 1*density){//手指滑动的高度大于每次加减的高度时才触发高度的修改,避免频繁修改,造成控件抖动
                                        Log.e(TAG,"ACTION_MOVE--------------------------->" + dur);
                                        controlHeader(dur);
                                    }
                                    downY = moveY;
                                    break;
                            }
                            return false;
                        }
                    });
            }
            @Override
            public void onScroll(AbsListView absListView, int i, int i1, int i2) {
                if(i==0){//当listView滑动到最顶端时,显示header控件,有些不自然,需要优化
                    showHeader(headerLayout, Float.valueOf(99 * density).intValue(), Float.valueOf(1 * density).intValue());
                }
            }
        });
    }



2.控制控件显示或隐藏代码

private void controlHeader(float dur) {
    height = headerLayout.getHeight();
    Log.e(TAG,"height---------->" + height);
    //100*density 父控件原始高度
    if(dur>0 && height < Float.valueOf(100*density).intValue()){//下,显示
        showHeader(headerLayout,height,Float.valueOf(1*density).intValue());
        isShow = true;
    }
    if(dur<0 && height > 0){//上,隐藏
        hideHeader(headerLayout, height, Float.valueOf(1 * density).intValue());
        isHide = true;
    }
}


3.隐藏控件代码及动画


/**
 *
 * @param view  需要隐藏的控件
 * @param height    此控件的高度(dip,非px)
 * @param offset   隐藏时每次减少的高度(dip,非px)
 */
private void hideHeader(View view, int height, int offset) {
    ViewGroup.LayoutParams params2 = view.getLayoutParams();
    params2.height = height - offset;
    view.setLayoutParams(params2);
    postScaleInAnimation(headerTabLayout, height, params2.height);
    postScaleInAnimation(headerTitleLayout, height, params2.height);
}

/**设置缩小动画
 * 每次缩小的是父控件,子控件只是设置一个动画
 * @param view  需要添加动画的控件
 * @param beforeHeight  父控件缩小之前的高度
 * @param afterHeight   父控件缩小之后的高度
 */
private void postScaleInAnimation(View view,int beforeHeight,int afterHeight) {
    //100*density 父控件原始高度
    float fromValue = beforeHeight / (100*density);
    float toValue = afterHeight / (100*density);
    Log.e(TAG, "缩小比例: " + toValue);
    ScaleAnimation myAnimationScaleIn = new ScaleAnimation(fromValue, toValue, fromValue, toValue,
            Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
            0.5f);
    myAnimationScaleIn.setInterpolator(new LinearInterpolator());
    myAnimationScaleIn.setFillAfter(true);
    view.startAnimation(myAnimationScaleIn);
}



4.显示控件代码及动画


/**
 *
 * @param view  需要显示的控件
 * @param height    此控件的高度(dip,非px)
 * @param offset    显示时每次增加的高度(dip,非px)
 */
private void showHeader(View view,int height,int offset) {
    ViewGroup.LayoutParams params1 = view.getLayoutParams();
    params1.height = height + offset;
    view.setLayoutParams(params1);
    postScaleOutAnimation(headerTabLayout,height,params1.height);
    postScaleOutAnimation(headerTitleLayout,height,params1.height);
}

/**设置放大动画
 * 每次放大的是父控件,子控件只是设置一个动画
 * @param view  需要添加动画的控件
 * @param beforeHeight  父控件放大之前的高度
 * @param afterHeight   父控件放大之后的高度
 */
private void postScaleOutAnimation(View view,int beforeHeight,int afterHeight) {
    //100*density 父控件原始高度
    float fromValue = beforeHeight / (100*density);
    float toValue = afterHeight / (100*density);
    Log.e(TAG, "扩大比例: " + toValue);
    ScaleAnimation myAnimationScaleOut = new ScaleAnimation(fromValue, toValue, fromValue, toValue,
            Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
            0.5f);
    myAnimationScaleOut.setInterpolator(new AccelerateInterpolator());
    myAnimationScaleOut.setFillAfter(true);
    view.startAnimation(myAnimationScaleOut);
}


完整代码(java)

----------------------------------------------------------------------------------------------------------------------------------------------------------


public class MainActivity extends BaseActivity {
    private String TAG = "MainActivity";
    private ListView listView;
    private LinearLayout headerLayout;
    private Integer[] data = new Integer[100];
    private float density;
    private int height;
    private LinearLayout headerTabLayout;
    private LinearLayout headerTitleLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        density = dm.density;
        findView();
        setListener();
    }

    private float downY;
    private float moveY;
    private boolean isFirst = true;
    private void setListener() {
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView listView, final int state) {
                    listView.setOnTouchListener(new View.OnTouchListener() {
                        @Override
                        public boolean onTouch(View v, MotionEvent event) {
                            int action = event.getAction();
                            switch (action) {
                                case MotionEvent.ACTION_CANCEL:
                                case MotionEvent.ACTION_UP:
//                                    Log.e(TAG,"ACTION_UP");
                                    isFirst = true;
                                    //抬起手指之后
                                    if(isShow){
                                        if(height > Float.valueOf(0.5f*density).intValue() ){//控件高度大于一定高度时,显示全部控件
                                            showHeader(headerLayout,Float.valueOf(99 * density).intValue(),Float.valueOf(1*density).intValue());
                                        }
                                        isShow = false;
                                    }

                                    if(isHide){
                                        if(height < Float.valueOf(99*density).intValue() ){//控件高度小于一定高度时,隐藏全部控件
                                            hideHeader(headerLayout,Float.valueOf(1 * density).intValue(),Float.valueOf(1*density).intValue());
                                        }
                                        isHide = false;
                                    }
                                    break;
                                case MotionEvent.ACTION_MOVE:
                                    if(isFirst){//记录第一次按下时的y坐标
                                        downY = event.getY();
                                        isFirst = false;
                                    }
                                    moveY = event.getY();
                                    float dur = moveY - downY;
                                    float temp = Math.abs(dur);
                                    if(temp > 1*density){//手指滑动的高度大于每次加减的高度时才触发高度的修改,避免频繁修改,造成控件抖动
                                        Log.e(TAG,"ACTION_MOVE--------------------------->" + dur);
                                        controlHeader(dur);
                                    }
                                    downY = moveY;
                                    break;
                            }
                            return false;
                        }
                    });
            }
            @Override
            public void onScroll(AbsListView absListView, int i, int i1, int i2) {
                if(i==0){//当listView滑动到最顶端时,显示header控件,有些不自然,需要优化
                    showHeader(headerLayout, Float.valueOf(99 * density).intValue(), Float.valueOf(1 * density).intValue());
                }
            }
        });
    }

    /**
     *
     * @param view  需要隐藏的控件
     * @param height    此控件的高度(dip,非px)
     * @param offset   隐藏时每次减少的高度(dip,非px)
     */
    private void hideHeader(View view, int height, int offset) {
        ViewGroup.LayoutParams params2 = view.getLayoutParams();
        params2.height = height - offset;
        view.setLayoutParams(params2);
        postScaleInAnimation(headerTabLayout, height, params2.height);
        postScaleInAnimation(headerTitleLayout, height, params2.height);
    }

    /**设置缩小动画
     * 每次缩小的是父控件,子控件只是设置一个动画
     * @param view  需要添加动画的控件
     * @param beforeHeight  父控件缩小之前的高度
     * @param afterHeight   父控件缩小之后的高度
     */
    private void postScaleInAnimation(View view,int beforeHeight,int afterHeight) {
        //100*density 父控件原始高度
        float fromValue = beforeHeight / (100*density);
        float toValue = afterHeight / (100*density);
        Log.e(TAG, "缩小比例: " + toValue);
        ScaleAnimation myAnimationScaleIn = new ScaleAnimation(fromValue, toValue, fromValue, toValue,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        myAnimationScaleIn.setInterpolator(new LinearInterpolator());
        myAnimationScaleIn.setFillAfter(true);
        view.startAnimation(myAnimationScaleIn);
    }

    /**
     *
     * @param view  需要显示的控件
     * @param height    此控件的高度(dip,非px)
     * @param offset    显示时每次增加的高度(dip,非px)
     */
    private void showHeader(View view,int height,int offset) {
        ViewGroup.LayoutParams params1 = view.getLayoutParams();
        params1.height = height + offset;
        view.setLayoutParams(params1);
        postScaleOutAnimation(headerTabLayout,height,params1.height);
        postScaleOutAnimation(headerTitleLayout,height,params1.height);
    }

    /**设置放大动画
     * 每次放大的是父控件,子控件只是设置一个动画
     * @param view  需要添加动画的控件
     * @param beforeHeight  父控件放大之前的高度
     * @param afterHeight   父控件放大之后的高度
     */
    private void postScaleOutAnimation(View view,int beforeHeight,int afterHeight) {
        //100*density 父控件原始高度
        float fromValue = beforeHeight / (100*density);
        float toValue = afterHeight / (100*density);
        Log.e(TAG, "扩大比例: " + toValue);
        ScaleAnimation myAnimationScaleOut = new ScaleAnimation(fromValue, toValue, fromValue, toValue,
                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                0.5f);
        myAnimationScaleOut.setInterpolator(new AccelerateInterpolator());
        myAnimationScaleOut.setFillAfter(true);
        view.startAnimation(myAnimationScaleOut);
    }

    private boolean isShow = false;
    private boolean isHide = false;
    private void controlHeader(float dur) {
        height = headerLayout.getHeight();
        Log.e(TAG,"height---------->" + height);
        //100*density 父控件原始高度
        if(dur>0 && height < Float.valueOf(100*density).intValue()){//下,显示
            showHeader(headerLayout,height,Float.valueOf(1*density).intValue());
            isShow = true;
        }
        if(dur<0 && height > 0){//上,隐藏
            hideHeader(headerLayout, height, Float.valueOf(1 * density).intValue());
            isHide = true;
        }
    }

    private void findView() {
        listView = (ListView) findViewById(R.id.content_list_view);
        headerLayout = (LinearLayout) findViewById(R.id.header);
        headerTabLayout = (LinearLayout) findViewById(R.id.header_tab_layout);
        headerTitleLayout = (LinearLayout) findViewById(R.id.header_title_layout);
        findViewById(R.id.tab1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"tab1",Toast.LENGTH_LONG).show();
            }
        });
        findViewById(R.id.tab2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(ScaleDialog.class);
                Toast.makeText(MainActivity.this,"tab2",Toast.LENGTH_LONG).show();
            }
        });
        findViewById(R.id.tab3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"tab3",Toast.LENGTH_LONG).show();
            }
        });
        setListView();
    }

    private void startActivity(Class<?> cls) {
        Intent intent = new Intent();
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        intent.setClass(MainActivity.this,cls);
        startActivity(intent);
    }

    private void setListView() {
        setData();
        ArrayAdapter adapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1,data);
        listView.setAdapter(adapter);
    }

    private void setData() {
        for(int i=0; i<data.length; i++){
            data[i] = i;
        }
    }
}

完整代码(xml文件)

----------------------------------------------------------------------------------------------------------------------------------------------------------


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

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="100dip"
        android:orientation="vertical"
        android:background="#44ff0000">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dip"
            android:orientation="horizontal"
            android:gravity="center"
            android:layout_weight="1"
            android:background="#4400ff00">
            <LinearLayout
                android:id="@+id/header_title_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:gravity="center">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="18sp"
                    android:text="Header"/>
            </LinearLayout>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dip"
            android:orientation="horizontal"
            android:gravity="center"
            android:layout_weight="1">
            <LinearLayout
                android:id="@+id/header_tab_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:gravity="center"
                android:paddingBottom="6dip"
                android:paddingTop="6dip">

                <Button
                    android:id="@+id/tab1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="tab1"/>
                <Button
                    android:id="@+id/tab2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft = "4dip"
                    android:layout_marginRight="4dip"
                    android:text="tab2"/>
                <Button
                    android:id="@+id/tab3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="tab3"/>
            </LinearLayout>

        </LinearLayout>
    </LinearLayout>
    <ListView
        android:id="@+id/content_list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

------------------