本文主要是介绍可以折叠Gridview,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
可以折叠Gridview
实现原理
1、折叠实现
重写gridview的setAdapter方法
@Override
public void setAdapter(ListAdapter adapter) {if (foldNm > 0) {//进行折叠adapter = new FoldViewGridAdapter(adapter, foldNm);}super.setAdapter(adapter);}
FoldViewGridAdapter是一个包装类,用来实现对当前的adapter包装,主要是重写getCount方法如下:
private class FoldViewGridAdapter implements WrapperListAdapter {...@Overridepublic int getCount() {//fn如果小于1,不进行折叠,根据是否折叠来判断,默认是折叠状态if (fn < 0) {return adapter.getCount();} else {//如果fn大于0,进行折叠处理if (expend) {return adapter.getCount();} else {return Math.min(adapter.getCount(), fn * getNumColumns());}}}@Overridepublic ListAdapter getWrappedAdapter() {return this;}...
}
先判断fn,也就是折叠后显示的行数,fn初始值为-1,也就是不折叠,当设置了fn值大于0,那么就需要进行折叠判断,如果需要折叠,则返回
return Math.min(adapter.getCount(), fn * getNumColumns());
两者中的最小值。fn * getNumColumns()是折叠时显示的行数和显示的列数的积,也就是显示的个数。
2、如何添加ExpendControlView
同样在重写setAdapter方法,对adapter进行再次封装。
HeaderViewGridAdapter headerViewGridAdapter = new HeaderViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
添加ExpendControlView的逻辑主要在HeaderViewGridAdapter中,HeaderViewGrideAdapter要实现一下几点:
1、怎么使添加的ExpendControlView,独占一行。
public void addExpendControlView(View v, Object data, boolean isSelectable, boolean isExpendControlView) {ViewGroup.LayoutParams lyp = v.getLayoutParams();FixedViewInfo info = new FixedViewInfo();FrameLayout fl = new FullWidthFixedViewLayout(getContext());if (lyp != null) {v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));fl.setLayoutParams(new LayoutParams(lyp.width, lyp.height));}fl.addView(v);info.view = v;info.viewContainer = fl;info.data = data;info.isSelectable = isSelectable;//控制是否可以折叠info.isExpendControlView = isExpendControlView;mFooterViewInfos.add(info);if (mAdapter != null) {((HeaderViewGridAdapter) mAdapter).notifyDataSetChanged();}}
在addExpendControlView方法中,会先创建一个fl的viewGroup,然后再把controlview添加到fl中,FullWidthFixedViewLayout的代码如下:
private class FullWidthFixedViewLayout extends FrameLayout {public FullWidthFixedViewLayout(Context context) {super(context);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {int realLeft = GridViewEnableFooter.this.getPaddingLeft() + getPaddingLeft();// Try to make where it should be, from left, full widthif (realLeft != left) {offsetLeftAndRight(realLeft - left);}super.onLayout(changed, left, top, right, bottom);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int targetWidth = GridViewEnableFooter.this.getMeasuredWidth()- GridViewEnableFooter.this.getPaddingLeft()- GridViewEnableFooter.this.getPaddingRight();widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth,MeasureSpec.getMode(widthMeasureSpec));super.onMeasure(widthMeasureSpec, heightMeasureSpec);}}
在onLayout和onMeasure的时候设置宽度和gridview的宽度一致,来设置fl的宽度和gridview的宽度一致,这样可以独占一行。
2、添加ExpendControlView后count的计算。
添加ExpendControlView需要重新计算adapter的getcount返回值,getCount方法如下:
public int getCount() {return getExpendControlViewsCount() * mNumColumns + getAdapterAndPlaceHolderCount();}
因为一个ExpendControlView会占一行,所以需要乘以列数,getAdapterAndPlaceHolderCount方法实现如下:
private int getAdapterAndPlaceHolderCount() {return (int) (Math.ceil(1f * mAdapter.getCount() / mNumColumns) * mNumColumns);}
getAdapterAndPlaceHolderCount用来补充数量,使得count个数为整数列的倍数。如果不是整数列,那么添加的ExpendControlView不会占用单独的行,显示有问题。
3、重写getView方法。
添加的ExpendControlView需要在getView中进行返回,所以还需要重写getView方法。
public View getView(int position, View convertView, ViewGroup parent) {// Adapterfinal int adjPosition = position - numHeadersAndPlaceholders;int adapterCount = 0;if (mAdapter != null) {adapterCount = getAdapterAndPlaceHolderCount();if (adjPosition < adapterCount) {if (adjPosition < mAdapter.getCount()) {return mAdapter.getView(adjPosition, convertView, parent);} else {if (convertView == null) {convertView = new View(parent.getContext());}convertView.setVisibility(View.INVISIBLE);convertView.setMinimumHeight(mRowHeight);return convertView;}}}// ExpendControlViewfinal int footerPosition = adjPosition - adapterCount;if (footerPosition < getCount()) {View footViewContainer = mFooterViewInfos.get(footerPosition / mNumColumns).viewContainer;if (position % mNumColumns == 0) {return footViewContainer;} else {if (convertView == null) {convertView = new View(parent.getContext());}// We need to do this because GridView uses the height of the last item// in a row to determine the height for the entire row.convertView.setVisibility(View.INVISIBLE);convertView.setMinimumHeight(footViewContainer.getHeight());return convertView;}}throw new ArrayIndexOutOfBoundsException(position);}
方法
1、添加底部控制view
public void addExpendControlView(View view)
2、设置折叠时展示的行数
setFoldNum(int foldNm)
用于设置折叠时显示的行数
使用方法
//折叠控制view
gridView.addFooterView(LoadMoreView(this))//设置折叠行数
gridView.setFoldNum(2)gridView.adapter = object : BaseAdapter() {...}
上面的loadMoreView就是底部的折叠控制view,添加自己的控制view时,继承下面接口
interface IExpendControl {/*** 展开*/fun expend()/*** 折叠*/fun fold()
}
重写expend和fold方法,也就是展开和折叠,完成控制。
class LoadMoreView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs), IExpendControl {private var viewBinding: LoadMoreViewBinding =LoadMoreViewBinding.inflate(LayoutInflater.from(context), this)override fun expend() {//展开时操作viewBinding.loadMore.text = "收起"viewBinding.arrow.setImageResource(R.drawable.up_arrow)}override fun fold() {//折叠时操作viewBinding.loadMore.text = "展开全部"viewBinding.arrow.setImageResource(R.drawable.down_arrow)}
}
源码地址
https://github.com/hankinghu/ExpendGridView
参考
https://github.com/liaohuqiu/android-GridViewWithHeaderAndFooter
这篇关于可以折叠Gridview的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!