解决嵌套在ScrollView的GridView Item高度不一致时高度不自适应
从1月8号开始就纠结,嵌套在ScrollView中的GridView,若是其Item高度不一致,导致GridView Item之间重叠,并且显示不全的问题。。。(ps:因为这个问题,眼睛一直盯着屏幕患了眼睑炎,内麦粒肿,而且还便秘,估计内里的火?反应到眼睛上了,cry)不过最后被老大轻轻松松给搞定,无地自容的赶脚。。。
首先讲一下为了解决这个问题尝试了哪些法子:
遇到这个问题在修改xml布局的一些属性无果后果然百度,百度的结果不尽人意啊,没有多少合适的,果断奔向Google,借用同事的VPN去stackoverflow查看相关问题,真的有哦,国外大神们post了一些解决方案,例如重写GridView禁止滑动,这个我也写了,还有就是重写Item的根布局RelativeLayout,在那里获取Item的高度,动态计算,始终觉得这个问题不是大问题只是很恶心而已没必要太大动干戈,so未采用那位大神的重写控件的方案。那剩下的就是在Adapter的getView方法中动态设置Item的高度,具体代码如下:
setHeight()方法详细如下图
按照上述方法依然没什么卵用啊,另外,在Activity中拿到Item的最大高度动态给GridView设置上,也是没有效果的;若是在Item的xml中写死一个够大的高度,GridView就会自动扩展了,这说明在public View getView(int position, View convertView, ViewGroup parent) 方法中,参数parent在初始化第一次的时候就必须拿到一个高度,否则GridView会始终默认最初的高而不扩展。理解parent的意义!!!parent是GridView的根布局
其实一直没解决这个问题主要是太纠结GridView的使用,想过使用其他控件代替,但是因在eclipse下开发,除了GridView其他的就是使用LinearLayout动态添加布局了(因Eclipse下RecyclerView没有最新的库,很多效果大打折扣,还有其他各种插件的使用,哎,抓紧换到Android Studio吧)考虑到使用LinearLayout,切换选中状态没有GridView的notifyDataSetChanged()灵活,迟迟不敢下手啊。
下面是老大灵活解决这个问题的方案:
自定义一个LinearLayout,在代码中编写一个标签的内容,供外部灵活调用改变数据及UI的接口,把代码po出来:
item_activity_tag_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="@+id/rl_tag_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:layout_marginTop="5dp"
android:background="@drawable/yuanjiao_blue_rect_line" >
<TextView
android:id="@+id/txt_title"
style="@style/item_txt_middle"
android:layout_centerInParent="true"
android:ellipsize="end"
android:gravity="center"
android:maxLines="4"
android:padding="3dp"
android:singleLine="false"
android:textColor="@color/activity_tag_color" />
<ImageView
android:id="@+id/img_selected"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_alignBottom="@id/rl_tag_layout"
android:layout_alignParentRight="true"
android:src="@drawable/icon_select_check"
android:visibility="visible" />
自定义ActivityTagLayout.java
public class ActivityTagLayout extends LinearLayout {
private Context context;
private LayoutInflater mInflater;
private RelativeLayout tagLayout;
private TextView mTitle;
private ImageView mSelectImg;
public ActivityTagLayout(Context context) {
super(context);
this.context = context;
mInflater = LayoutInflater.from(context);
initView();
}
private void initView() {
View view = mInflater.inflate(R.layout.item_activity_tag_layout, null);
tagLayout = (RelativeLayout) view.findViewById(R.id.rl_tag_layout);
mTitle = (TextView) view.findViewById(R.id.txt_title);
mSelectImg = (ImageView) view.findViewById(R.id.img_selected);
this.addView(view);
}
/**
- 给当前Layout设置数据
*
- @param bean
*/
public void setData(ActivityTagBean bean) {
mTitle.setText(bean.name);
if (bean.isSelected) {
mSelectImg.setVisibility(View.VISIBLE);
tagLayout.setBackgroundResource(R.drawable.yuanjiao_blue_rect_bg);
mTitle.setTextColor(context.getResources().getColor(
R.color.WhiteColor));
} else {
mSelectImg.setVisibility(View.GONE);
tagLayout.setBackgroundResource(R.drawable.yuanjiao_blue_rect_line);
mTitle.setTextColor(context.getResources().getColor(
R.color.activity_tag_color));
}
}
/**
- 根据是否选中刷新UI
*
- @param isSelected
*/
public void resetTagSelect(boolean isSelected) {
if (isSelected) {
mSelectImg.setVisibility(View.VISIBLE);
tagLayout.setBackgroundResource(R.drawable.yuanjiao_blue_rect_bg);
mTitle.setTextColor(context.getResources().getColor(
R.color.WhiteColor));
} else {
mSelectImg.setVisibility(View.GONE);
tagLayout.setBackgroundResource(R.drawable.yuanjiao_blue_rect_line);
mTitle.setTextColor(context.getResources().getColor(
R.color.activity_tag_color));
}
}
}
在Activity中,有个LinearLayout容器用于添加标签:tagContainer,在获取数据的接口下调用下面的方法;
activityTagBeans为数据集合(ArrayList),因要求布局每行3列,根据总数计算所需行数
private void setActivityTagDatas() {
tagContainer.removeAllViews();
int row = 0;// 计算需要行数
if ((activityTagBeans.size() % 3) == 0) {
row = activityTagBeans.size() / 3;
} else {
row = (activityTagBeans.size() / 3) + 1;
}
for (int i = 0; i < row; i++) {
LinearLayout rowLayout = new LinearLayout(context);
rowLayout.setOrientation(LinearLayout.HORIZONTAL);
rowLayout.setWeightSum(3);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
rowLayout.setLayoutParams(params);
addActivityTag(i, rowLayout);
tagContainer.addView(rowLayout);
}
}
/**
-
添加每行数据
-
@param row 行
-
@param layout
*/
private void addActivityTag(int row, LinearLayout layout) {
for (int i = 0; i < 3; i++) {
final int position = (row * 3 + i);
if (position < activityTagBeans.size()) {
ActivityTagLayout tagLayout = new ActivityTagLayout(this);
// params中的width置为0,这样才能保证跟布局weightSum=3起作用
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
0, LinearLayout.LayoutParams.WRAP_CONTENT);
params.weight = 1;// 此处weight必须置为1
params.bottomMargin = 10;
tagLayout.setData(activityTagBeans.get(position));
tagLayout.setLayoutParams(params);
tagLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
StatisticsUtil.customEvent(PageSettings.ACTIVITY_RELEASE_NEW_DYNAMIC,
String.format(getString(R.string.dynamic_release_activity_choose_click), activityTagBeans.get(position).name));
activityTagBeans.get(position).isSelected = !activityTagBeans.get(position).isSelected;
if (lastTagPosition != -1 && lastTagPosition != position) {
activityTagBeans.get(lastTagPosition).isSelected = false;
}
resetTagSelected(position);
if (activityTagBeans.get(position).isSelected) {
if (tvActivityDesc.getVisibility() == View.INVISIBLE) {
tvActivityDesc.setVisibility(View.VISIBLE);
}
activityId = activityTagBeans.get(position).activityId;
if (J_CommonUtils.isEmpty(activityTagBeans.get(position).desc)
&& !J_CommonUtils.isEmpty(activityTagBeans.get(position).showTime)) {
tvActivityDesc.setText(activityTagBeans.get(position).showTime);
} else if (!J_CommonUtils.isEmpty(activityTagBeans.get(position).desc)
&& J_CommonUtils.isEmpty(activityTagBeans.get(position).showTime)) {
tvActivityDesc.setText(activityTagBeans.get(position).desc);
} else if (!J_CommonUtils.isEmpty(activityTagBeans.get(position).desc)
&& !J_CommonUtils.isEmpty(activityTagBeans.get(position).showTime)) {
tvActivityDesc.setText(activityTagBeans.get(position).desc + "nn"
+ activityTagBeans.get(position).showTime);
} else {
tvActivityDesc.setVisibility(View.INVISIBLE);
}
} else {
activityId = "";
tvActivityDesc.setVisibility(View.INVISIBLE);
}
lastTagPosition = position;
if (!isBottom) {
J_Application.handler.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
isBottom = true;
}
});
}
}
});
layout.addView(tagLayout);
}
}
}
/**
- 重置选中状态
*/
private void resetTagSelected(final int selectIndex) {
for (int i = 0; i < tagContainer.getChildCount(); i++) {
LinearLayout rowLayout = (LinearLayout) tagContainer.getChildAt(i);
for (int k = 0; k < rowLayout.getChildCount(); k++) {
final ActivityTagLayout tagLayout = (ActivityTagLayout) rowLayout
.getChildAt(k);
if ((i * 3 + k) == selectIndex) {
tagLayout.resetTagSelect(activityTagBeans.get(selectIndex).isSelected);
} else {
tagLayout.resetTagSelect(false);// 根据重写的Layout灵活修改选中状态
}
}
}
}
最终效果图如下:
改变状态充分利用tagContainer.getChildAt(i)获取每个子Item!!!这点我竟然没想到,哎,思维太局限了!!!以此谨记