ScrollView中使用ListView、GridView以及展开、收缩动画

在使用listView和gridview的时候,无意中发现了布局中的一个小问题。下面,我会按照步骤一步一步详细解释。随后,会给出ScrollView中使用ListView、GridView以及展开、收缩动画。

第一个需求:在Activity中,有一个Textview,底部和右侧各有一条竖线。
这个需求太简单了。分分钟、妥妥的写完

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#55ff0000"
    android:orientation="horizontal"
    >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <TextView
            android:id="@+id/grid_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#5500ff00"
            android:gravity="center"
            android:textSize="25sp"
            />

        <View
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:background="#ffff00"/>

        <View
            android:layout_width="30dp"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:background="#ffff00"/>

    </RelativeLayout>

</LinearLayout>
public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

效果如下:
这里写图片描述

绿色是Textview,黄色的是线。

现在,需求变了。
第二个需求,把这个布局移到ListView或者Gridview中。

这也很简单。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#55ff0000"
    android:orientation="vertical"
    >

    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <GridView
        android:id="@+id/grideview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:numColumns="3"
        android:stretchMode="columnWidth"/>

</LinearLayout>

item.xml的布局如下:

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >

        <TextView
            android:id="@+id/item_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#5500ff00"
            android:gravity="center"
            android:textSize="25sp"
            />

        <View
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:layout_alignParentBottom="true"
            android:background="#ffff00"/>

        <View
            android:layout_width="5dp"
            android:layout_height="match_parent"
            android:layout_alignParentEnd="true"
            android:background="#ffff00"/>

    </RelativeLayout>

</LinearLayout>
package com.chen.demo;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity2 extends Activity {

    private Context mContext;

    private ListView listview;
    private ArrayList<String> listviewList;
    private MyListViewAdapter listViewAdapter;

    //---------------------------------------

    private GridView grideview;
    private ArrayList<String> gridviewList;
    private MyGridViewAdapter gridViewAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        mContext = this;

        listview = findViewById(R.id.listview);

        listviewList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            listviewList.add("listview==" + i);
        }

        listViewAdapter = new MyListViewAdapter();

        listview.setAdapter(listViewAdapter);

        //------------------------------------

        grideview = findViewById(R.id.grideview);
        gridviewList = new ArrayList<>();

        for (int i = 0; i < 6; i++) {
            gridviewList.add("grid==" + i);
        }

        gridViewAdapter = new MyGridViewAdapter();
        grideview.setAdapter(gridViewAdapter);

    }


    //ListView数据适配器
    private class MyListViewAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return listviewList.size();
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);
                viewHolder = new ViewHolder();

                viewHolder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);

                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.item_tv.setText(listviewList.get(position));

            return convertView;
        }

        private class ViewHolder {
            private TextView item_tv;
        }
    }

    //GridView数据适配器
    private class MyGridViewAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return gridviewList.size();
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null);
                viewHolder = new ViewHolder();

                viewHolder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);

                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.item_tv.setText(gridviewList.get(position));

            return convertView;
        }

        private class ViewHolder {
            private TextView item_tv;
        }
    }


}

效果如下:
这里写图片描述

what,竖线呢?布局没问题啊!
我要出大招了,自定义!!!

public class LineView extends View {

    public LineView(Context context) {
        this(context,null);
    }

    public LineView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.e("w",w+"");
        Log.e("h",h+"");
    }

}

现在,用这个LineView,替换item中的右侧的竖线

 <com.chen.demo.LineView
     android:layout_width="5dp"
     android:layout_height="match_parent"
     android:layout_alignParentEnd="true"
     android:background="#ffff00"/>

其余不变,运行,结果还是不展示竖线。控制台打印日志:

com.chen.demo E/w: 15
com.chen.demo E/h: 0
com.chen.demo E/w: 15
com.chen.demo E/h: 0
com.chen.demo E/w: 15
com.chen.demo E/h: 0
com.chen.demo E/w: 15
com.chen.demo E/h: 0
com.chen.demo E/w: 15
com.chen.demo E/h: 0
com.chen.demo E/w: 15
com.chen.demo E/h: 0
......
......

竖线没有测量到高度,也就是说,高度是0。

现在,再回到原来的view,限定高度是10dp

 <View
     android:layout_width="5dp"
     android:layout_height="10dp"
     android:layout_alignParentEnd="true"
     android:background="#ffff00"/>

运行后,结果如下:
这里写图片描述

竖线终于出来了。

是RelativeLayout中的 android:layout_height=”match_parent”影响吗?
现在,重新布局item,用LinearLayout做框架

item2.xml

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

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1">

            <TextView
                android:id="@+id/item_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#5500ff00"
                android:gravity="center"
                android:textSize="25sp"
                />

            <View
                android:layout_width="match_parent"
                android:layout_height="3dp"
                android:layout_alignParentBottom="true"
                android:background="#ffff00"/>

        </RelativeLayout>

        <View
            android:layout_width="3dp"
            android:layout_height="match_parent"
            android:background="#ffff00"/>

    </LinearLayout>
</LinearLayout>

Activity中的代码基本不变,在adapter中注意应用这个新的item2就行
运行,结果如下:
这里写图片描述

现在,出来了。LinearLayout下,android:layout_height=”match_parent”,也正常显示了。

现在,又有新需求了

一个界面中,ListView那样的展示几条数据,然后gridview那样展示几条数据,接口一次性返回,不存在分页加载。点击一个按钮,这个listView或者gridview,要有动画的展开或收缩。

思路整理:
既然设计图展示效果想ListView和Gridview,没商量,肯定是用这个2个了,因为数据是接口一次性返回,不存在分页加载,但是还要在屏幕一次性展示,就要考虑不同的手机,一屏放不下。是需要有滑动功能的,肯定要用
ScrollView。

但是如果直接用ListView和GridView,会有问题,只会显示一行。关于这个问题,我就不多说了,请看我的上一篇博客

http://blog.csdn.net/u014620028/article/details/78657507

这里我, 直接上代码了

import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;

/**
 * 重新测量了高度,针对解决ScrollView中,只显示一行的问题
 */
public class ScrollViewGridView extends GridView {
    public ScrollViewGridView(Context context) {
        this(context, null);
    }

    public ScrollViewGridView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

/**
 * 重新测量了高度,针对解决ScrollView中,只显示一行的问题
 */
public class ScrollViewListView extends ListView {
    public ScrollViewListView(Context context) {
        this(context, null);
    }

    public ScrollViewListView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

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

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }

}

下面,是Activity的布局代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#55ff0000"
    android:orientation="vertical"
    >

    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/listview_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:paddingBottom="5dp"
                android:paddingTop="5dp"
                android:text="listview的展开或收缩"
                android:textSize="20sp"/>

            <RelativeLayout
                android:id="@+id/listview_rl"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <com.chen.demo.ScrollViewListView
                    android:id="@+id/listview"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"/>

            </RelativeLayout>

            <!--<com.chen.demo.ScrollViewListView-->
            <!--android:id="@+id/listview"-->
            <!--android:layout_width="match_parent"-->
            <!--android:layout_height="match_parent"/>-->

            <TextView
                android:id="@+id/gridview_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:paddingBottom="5dp"
                android:paddingTop="5dp"
                android:text="gridview的展开或收缩"
                android:textSize="20sp"/>

            <RelativeLayout
                android:id="@+id/gridview_rl"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <com.chen.demo.ScrollViewGridView
                    android:id="@+id/gridview"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:numColumns="3"
                    android:stretchMode="columnWidth"/>
            </RelativeLayout>

            <!--<com.chen.demo.ScrollViewGridView-->
            <!--android:id="@+id/grideview"-->
            <!--android:layout_width="match_parent"-->
            <!--android:layout_height="wrap_content"-->
            <!--android:gravity="center"-->
            <!--android:numColumns="3"-->
            <!--android:stretchMode="columnWidth"/>-->

        </LinearLayout>

    </ScrollView>

</LinearLayout>

listView和gridview的item布局,就是上面的item2.xml
Activity中的代码如下:

package com.chen.demo;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;

public class MainActivity3 extends Activity {

    private Context mContext;

    private ScrollViewListView listview;
    private ArrayList<String> listviewList;
    private MyListViewAdapter listViewAdapter;
    //listview的高度
    private int listviewHeight;
    private boolean listviewIsExpand = true;

    private RelativeLayout listview_rl;

    //---------------------------------------

    private ScrollViewGridView gridview;
    private ArrayList<String> gridviewList;
    private MyGridViewAdapter gridViewAdapter;

    //listview的高度
    private int gridviewHeight;
    private boolean gridviewIsExpand = true;

    private RelativeLayout gridview_rl;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);

        mContext = this;

        listview_rl = findViewById(R.id.listview_rl);
        listview = findViewById(R.id.listview);

        listviewList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            listviewList.add("listview==" + i);
        }

        listViewAdapter = new MyListViewAdapter();

        listview.setAdapter(listViewAdapter);

        listview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //一般用完之后,立即移除该监听
                listview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                listviewHeight = listview.getMeasuredHeight();

            }
        });

        findViewById(R.id.listview_tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Log.e("listview_tv", "is click");

                ValueAnimator desAnimator = null;
                if (listviewIsExpand) {
                    desAnimator = ValueAnimator.ofInt(listviewHeight, 0);
                } else {
                    desAnimator = ValueAnimator.ofInt(0, listviewHeight);
                }

                desAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animator) {

                        int currentHeight = (Integer) animator.getAnimatedValue();
                        Log.e("onAnimationUpdate", "currentHeight==" + currentHeight);

                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) listview_rl.getLayoutParams();
                        params.height = currentHeight;
                        listview_rl.requestLayout();
                        //LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) listview.getLayoutParams();
                        //params.height = currentHeight;
                        //listview.requestLayout();
                    }
                });
                desAnimator.setDuration(2000);
                desAnimator.addListener(new ListViewAnimListener());
                desAnimator.start();
            }
        });

        //------------------------------------

        gridview_rl = findViewById(R.id.gridview_rl);
        gridview = findViewById(R.id.gridview);
        gridviewList = new ArrayList<>();

        for (int i = 0; i < 6; i++) {
            gridviewList.add("grid==" + i);
        }

        gridViewAdapter = new MyGridViewAdapter();
        gridview.setAdapter(gridViewAdapter);


        gridview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //一般用完之后,立即移除该监听
                gridview.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                gridviewHeight = gridview.getMeasuredHeight();

            }
        });

        findViewById(R.id.gridview_tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ValueAnimator desAnimator = null;
                if (gridviewIsExpand) {
                    desAnimator = ValueAnimator.ofInt(gridviewHeight, 0);
                } else {
                    desAnimator = ValueAnimator.ofInt(0, gridviewHeight);
                }

                desAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animator) {
                        int currentHeight = (Integer) animator.getAnimatedValue();

                        LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) gridview_rl.getLayoutParams();
                        params.height = currentHeight;
                        gridview_rl.requestLayout();
                    }
                });
                desAnimator.setDuration(2000);
                desAnimator.addListener(new GridViewAnimListener());
                desAnimator.start();
            }
        });


    }


    //ListView数据适配器
    private class MyListViewAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return listviewList.size();
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item2, null);
                viewHolder = new ViewHolder();

                viewHolder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);

                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.item_tv.setText(listviewList.get(position));

            return convertView;
        }

        private class ViewHolder {
            private TextView item_tv;
        }
    }


    //listview的动画监听
    private class ListViewAnimListener implements Animator.AnimatorListener {
        @Override
        public void onAnimationCancel(Animator arg0) {
        }

        @Override
        public void onAnimationEnd(Animator arg0) {
            Log.e("onAnimationEnd", "onAnimationEnd");
            listviewIsExpand = !listviewIsExpand;
        }

        @Override
        public void onAnimationRepeat(Animator arg0) {
        }

        @Override
        public void onAnimationStart(Animator arg0) {
            Log.e("onAnimationStart", "onAnimationStart");
        }
    }


    //GridView数据适配器
    private class MyGridViewAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return gridviewList.size();
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = LayoutInflater.from(mContext).inflate(R.layout.item2, null);
                viewHolder = new ViewHolder();

                viewHolder.item_tv = (TextView) convertView.findViewById(R.id.item_tv);

                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.item_tv.setText(gridviewList.get(position));

            return convertView;
        }

        private class ViewHolder {
            private TextView item_tv;
        }
    }

    //gridview的动画监听
    private class GridViewAnimListener implements Animator.AnimatorListener {
        @Override
        public void onAnimationCancel(Animator arg0) {
        }

        @Override
        public void onAnimationEnd(Animator arg0) {
            gridviewIsExpand = !gridviewIsExpand;
        }

        @Override
        public void onAnimationRepeat(Animator arg0) {
        }

        @Override
        public void onAnimationStart(Animator arg0) {
        }
    }


}

说明:大家应该有注意到,在布局的时候,我给ScrollViewListView外面包了一层RelativeLayout。在Activity中用的时候,是这个RelativeLayout在重新设置新高度

LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) listview_rl.getLayoutParams();
params.height = currentHeight;
listview_rl.requestLayout();

。这是因为,ListView已经在自定义的时候高度被自己定义的规则测量过了,就是你填充数据后的高度,不会再变化了。所以要,外包一层,通过它的变化,来影响ListView的高度。Gridview同理。

我会做动态图,效果就不展示了。把上面代码复制到自己的demo中就可以跑起来的。

猜你喜欢

转载自blog.csdn.net/u014620028/article/details/78708426