在使用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中就可以跑起来的。