android网格导航的实现

简介: 如今的很多app都在首页有一个可以滑动的导航

如今的很多app都在首页有一个可以滑动的导航,像美团App在首页上也有,如图:
image.png

还有很多的app也有,比如京东、饿了么等等,这个功能实现起来其实也不难,有RecycleView就可以,因为RecycleView有一个网格的布局,但是为了使用方便,还有就是以后其他的项目也需要用到,所以我把这个功能做了一个封装,全都封装在一个.java类里面,使用的时候就只需要在布局中引用该控件,同时在Activity或是Fragment中添加几行代码就可以使用整个功能。

这里将分别使用 java代码 跟 kotlin代码 实现这个功能

我封装的类名为EntryListView.java,将这个类放到自己的项目中。

一。先看使用方式

在布局中引用该控件
image.png

在布局对应activity或是Fragment中添加如下代码
image.png

mEntryList是我封装的EntryListView.java这个类的对象,第一行代码是设置行数跟列数,第二行代码中的listEntry是一个List对象,里面存放着每个item的内容,比如可以这样写,其中Entry.java是存放信息的实体类
image.png

好了这样就可以实现整个功能了,给大家看一下我自己这边的效果图
image.png

二。简单说一下我封装的EntryListView.java里面实现的原理,我这里使用的是ViewPager来实现滑动切换的,ViewPager的每一页都是一个GridView,这个大家都知道,他就是网格布局,然后网格布局里面的每一个item,就是一个图标跟一个标题,整个过程都是动态创建布局,没有引用到布局文件,只有这样移植性才比较强,只需要把我的这个EntryListView.java引用到自己的项目中,通过上面的方法是使用,就可以了。

下面是大家关系的问题,那就是源码啦,下面就是源码,里面注释很清晰,看了都懂,直接拿走不谢,觉得好的话多关注点个喜欢就行(微笑)

java代码

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
 
import qin.zszc.com.basiclib.R;
import qin.zszc.com.basiclib.support.imageloader.ImageLoader;
import qin.zszc.com.basiclib.widget.custom.entrynavigation.model.Entry;
 
/**
 * Created by xcfor on 2018/7/11.
 * 首页导航栏
 */
 
public class EntryListView extends FrameLayout implements ViewPager.OnPageChangeListener {
 
    private final int IND_WIDTH_SIZE = 6; //指示器默认宽的长度
 
    private Context mContext;
    private ViewPager mViewPager;
    private PagerAdapter mAdapter;
    private MyGridViewAdapter mMyGridViewAdpter;
    private LinearLayout mIndecatorLayout;
 
    private int mColumNum = 5;//多少列
    private int mRowNum = 2;//多少行
    private int mPageSize = 8;//每页多少个
    private int mCount;//滑动页面的数量
    private int mPrePosition = 0; //历史页pos
    private int mIndicatorWidth;//指示器宽度
    private int mIndicatorHight = 3;//指示器高度
    private int mCurrentPos = 0;//当前页pos
    private int mIconSize = 40; //item中图片的宽高
    private int mTextSize = 11; //item中字体的大小
 
    private List<List<Entry>> mResultList;//分页后的数据列表
    private List<Entry> mLists;//获取到的数据列表
    private List<View> mItemView = new ArrayList<>();//存放gridView的列表
 
    public EntryListView(@NonNull Context mContext) {
        super(mContext);
        this.mContext = mContext;
    }
 
    public EntryListView(@NonNull Context mContext, @Nullable AttributeSet attrs) {
        super(mContext, attrs);
        this.mContext = mContext;
    }
 
    public EntryListView(@NonNull Context mContext, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(mContext, attrs, defStyleAttr);
        this.mContext = mContext;
    }
 
    public void setPageSize(int rowNum,int colNum){
        mRowNum=rowNum;
        mColumNum=colNum;
        mPageSize=rowNum*colNum;
    }
 
    public void init() {
        if (mAdapter == null) {
            return;
        }
        mViewPager.setAdapter(mAdapter);
 
        //切换画面
        mViewPager.setPageTransformer(true, new EntryListView.MyPageTransformer());
        mIndecatorLayout.removeAllViews();
 
        //向线性布局中添加小圆点指示器
        View line;
        LinearLayout.LayoutParams params;
        for (int i = 0; i < mCount; i++) {
            line = new View(mContext);
            line.setId(i);
            params = new LinearLayout.LayoutParams(dip2px(mIndicatorWidth), dip2px(mIndicatorHight));
            params.setMargins(dip2px(3), 0, dip2px(3), 0);
            line.setLayoutParams(params);
            line.setBackgroundResource(R.drawable.basiclib_line_bg_selector);
            line.setEnabled(false);//默认设为非选中
            mIndecatorLayout.setGravity(Gravity.CENTER_HORIZONTAL);
            mIndecatorLayout.addView(line);
        }
        mIndecatorLayout.getChildAt(0).setEnabled(true);
        mViewPager.setCurrentItem(0);
    }
 
    /**
     * 获取数据
     * @param mLists
     */
    public void setData(List<Entry> mLists) {
        if (mLists.isEmpty()) {
            return;
        }
        this.mLists = mLists;
        mCount = pageNum();
        cutOutList(mLists, mPageSize);
        if (mAdapter == null) {
            mAdapter = new EntryListView.MyEntryAdapter(mItemView);
        }
        init();
    }
 
    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    private int dip2px(float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
 
 
    /**
     * 按照size的大小截取list
     *
     * @param lists
     * @param size
     * @return
     */
    public List<List<Entry>> cutOutList(List<Entry> lists, int size) {
        mResultList = new ArrayList<>();
        int arrSize = lists.size() % size == 0 ? lists.size() / size : lists.size() / size + 1;
        for (int i = 0; i < arrSize; i++) {
            List<Entry> sub = new ArrayList<>();
            for (int j = i * size; j <= size * (i + 1) - 1; j++) {
                if (j <= lists.size() - 1) {
                    sub.add(lists.get(j));
                }
            }
            mResultList.add(sub);
        }
        return mResultList;
    }
 
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
 
        //初始化Viewpager(应用入口列表)
        mIndicatorWidth = dip2px(IND_WIDTH_SIZE);
        LinearLayout llContent = new LinearLayout(mContext);
        llContent.setOrientation(LinearLayout.VERTICAL);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        mViewPager = new customViewPager(mContext);
        mViewPager.setLayoutParams(params);
        llContent.addView(mViewPager);
 
        //初始化指示器容器
        mIndecatorLayout = new LinearLayout(mContext);
        params.bottomMargin = 28;
        mIndecatorLayout.setLayoutParams(params);
        mIndecatorLayout.setOrientation(LinearLayout.HORIZONTAL);
        llContent.addView(mIndecatorLayout);
        mViewPager.addOnPageChangeListener(this);
        addView(llContent);
    }
 
 
    /**
     * 计算出页面的数量
     * @return
     */
    public int pageNum() {
        if (mLists.size() % mPageSize != 0 && mLists.size() / mPageSize < 1) {
            mCount = 1;
        } else if (mLists.size() % mPageSize != 0 && mLists.size() / mPageSize >= 1) {
            mCount = mLists.size() / mPageSize + 1;
        } else {
            mCount = mLists.size() / mPageSize;
        }
        return mCount;
    }
 
 
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }
 
    @Override
    public void onPageSelected(int position) {
        mCurrentPos = position;
        mIndecatorLayout.getChildAt(mPrePosition % mCount).setEnabled(false);
        mIndecatorLayout.getChildAt(mCurrentPos % mCount).setEnabled(true);//设置true放后面,防止初始化时两个pos都为0时。没有默认选中
        mPrePosition = mCurrentPos;
    }
 
    @Override
    public void onPageScrollStateChanged(int state) {
 
    }
 
 
    /**
     * 导航Viewpager的适配器,向ViewPager的每一个页中添加一个GridView
     */
    class MyEntryAdapter extends PagerAdapter {
        List<View> listItem;//前面加类型
 
        public MyEntryAdapter(List<View> itemView) {
            this.listItem = itemView;
        }
 
        @Override
        public int getCount() {
            return mCount;
        }
 
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            //向Viewpager每一页中添加一个gridView布局
            for (int i = 0; i < mCount; i++) {
                GridView gridView = new CustomGridView(mContext);
                gridView.setNumColumns(mColumNum);
                gridView.setGravity(Gravity.CENTER);
                gridView.setPadding(2, 2, 2, 0);
                listItem.add(gridView);
                mMyGridViewAdpter = new MyGridViewAdapter(mContext, mResultList.get(i), 0, mPageSize);
                gridView.setAdapter(mMyGridViewAdpter);
            }
            container.addView(listItem.get(position));
            return listItem.get(position);
        }
 
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }
 
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
 
 
    /**
     * 导航gridView的适配器,向gridView的每一项中添加信息
     */
    class MyGridViewAdapter extends BaseAdapter {
 
        private Context context;
        private List<Entry> lists;
        private int index;//页数小标,标示第几页,从0开始
        private int mPargerSize;//每页显示的最大的数量
 
        public MyGridViewAdapter(Context context, List<Entry> lists, int index, int mPargerSize) {
            this.context = context;
            this.lists = lists;
            this.index = index;
            this.mPargerSize = mPargerSize;
        }
 
        @Override
        public int getCount() {
            return lists.size() > (index + 1) * mPargerSize ?
                    mPargerSize : (lists.size() - index * mPargerSize);
        }
 
        @Override
        public Object getItem(int i) {
            return lists.get(i + index * mPargerSize);
        }
 
        @Override
        public long getItemId(int i) {
            return i + index * mPargerSize;
        }
 
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            return addGridViewChildLayout(view, i);
        }
 
        /**
         * 动态创建gridView的子布局
         *
         * @param view
         */
        public View addGridViewChildLayout(View view, int pos) {
            LinearLayout ll = new LinearLayout(context);
            GridView.LayoutParams llparams = new GridView.LayoutParams(GridView.LayoutParams.MATCH_PARENT, GridView.LayoutParams.MATCH_PARENT);
            ll.setOrientation(LinearLayout.VERTICAL);
            ll.setLayoutParams(llparams);
            ll.setPadding(0, dip2px(10), 0, 0);
            ll.setGravity(Gravity.CENTER);
            LinearLayout.LayoutParams img_params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            LinearLayout.LayoutParams tv_params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            ImageView img = new ImageView(context);
            img.setScaleType(ImageView.ScaleType.FIT_XY);
            img_params.gravity = Gravity.CENTER;
            img_params.width = dip2px(mIconSize);
            img_params.height = dip2px(mIconSize);
            img.setLayoutParams(img_params);
            ll.addView(img);
            TextView textView = new TextView(context);
            textView.setTextSize(mTextSize);
            textView.setTextColor(getResources().getColor(R.color.basiclib_colorBack));
            textView.setPadding(0, 20, 0, 0);
            textView.setLayoutParams(tv_params);
            ll.addView(textView);
            view = ll;
            ImageLoader.display(lists.get(pos).getEntryIocn(),img,R.mipmap.basicres_picture_default,R.mipmap.basicres_picture_default);
            textView.setText(lists.get(pos).getEntryName());
            return view;
        }
 
    }
 
    /**
     * 定义viewpager滑动效果
     */
    private class MyPageTransformer implements ViewPager.PageTransformer {
 
        @Override
        public void transformPage(View page, float position) {
            final float normalizedposition = Math.abs(Math.abs(position) - 1);
            page.setAlpha(normalizedposition);
        }
    }
 
    /**
     * 自定义Viewpager,计算viewPager高度
     */
    private class customViewPager extends ViewPager {
 
        public customViewPager(Context context) {
            super(context);
        }
 
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int height = 0;
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                child.measure(widthMeasureSpec,
                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                int h = child.getMeasuredHeight();
                if (h > height)
                    height = h;
            }
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                    MeasureSpec.EXACTLY);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
 
    /**
     * 自定义GridView,计算GridView高度
     */
    private class CustomGridView extends GridView {
        public CustomGridView(Context context) {
            super(context);
        }
 
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
        }
    }
}

kotlin代码

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import com.bumptech.glide.Glide
import com.example.testproject.R
import com.example.testproject.bean.Entry
 
class EntryListView : FrameLayout, ViewPager.OnPageChangeListener {
    private val IND_WIDTH_SIZE = 6f //指示器默认宽的长度
 
    private var mContext: Context? = null
    private var mViewPager: ViewPager? = null
    private var mAdapter: PagerAdapter? = null
    private var mMyGridViewAdapter: MyGridViewAdapter? = null
    private var mIndecatorLayout: LinearLayout? = null
 
    private var mColumNum = 5 //多少列
    private var mRowNum = 2 //多少行
    private var mPageSize = 8 //每页多少个
    private var mCount = 0 //滑动页面的数量
    private var mPrePosition = 0 //历史页pos
    private var mIndicatiorWidth = 0.0f //指示器宽度
    private var mIndicatiorHight = 3f //指示器高度
    private var mCurrentPos = 0 //当前也pos
    private var mIconSize = 40f //item中图片的宽高
    private var mTextSize = 11f //item中字体的大小
 
    private var mResultList: MutableList<List<Entry>>? = null //分页后的数据列表
    private var mLists: List<Entry>? = null //获取到的数据列表
    private var mItemView: MutableList<View> = ArrayList() //存放gridView的列表
 
    constructor(context: Context) : super(context) {
        this.mContext = context
    }
 
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        this.mContext = context
    }
 
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
 
    /**
     * 设置几行几列
     */
    fun setPageSize(rowNum: Int, colNum: Int) {
        mRowNum = rowNum
        mColumNum = colNum
        mPageSize = rowNum * colNum
    }
 
    /**
     * 初始化指示器
     */
    private fun init() {
        if (mAdapter == null) return
        mViewPager?.adapter = mAdapter
        //切换画面
        mViewPager?.setPageTransformer(true, MyPageTransformer())
        mIndecatorLayout?.removeAllViews()
        //向线性布局中添加小圆点指示器
        var line: View?
        var params: LinearLayout.LayoutParams?
        for (item in 0 until mCount) {
            line = View(mContext)
            line.id = item
            params = LinearLayout.LayoutParams(dip2px(mIndicatiorWidth), dip2px(mIndicatiorHight))
            params.setMargins(dip2px(3f), 0, dip2px(3f), 0)
            line.layoutParams = params
            line.setBackgroundResource(R.mipmap.ic_launcher)
            line.isEnabled = false
            mIndecatorLayout?.gravity = Gravity.CENTER_HORIZONTAL
            mIndecatorLayout?.addView(line)
        }
        mIndecatorLayout?.getChildAt(0)?.isEnabled = true
        mViewPager?.currentItem = 0
    }
 
    /**
     * 获取数据
     */
    fun setData(mLists: MutableList<Entry>) {
        if (mLists.isEmpty()) return
        this.mLists = mLists
        mCount = pageNum()
        cutOutList(mLists, mPageSize)
        if (mAdapter == null)
            mAdapter = MyEntryAdapter(mItemView)
        init()
    }
 
    /**
     * 按照size的大小截取list
     */
    private fun cutOutList(lists: List<Entry>, size: Int): List<List<Entry>> {
        mResultList = ArrayList()
        val arrSize: Int = if (lists.size % size == 0) {
            lists.size / size
        } else lists.size / size + 1
        for (item in 0 until arrSize) {
            val sub = ArrayList<Entry>()
            for (i in (item * size) until size * (item + 1)) {
                if (i <= lists.size - 1) {
                    sub.add(lists[i])
                }
            }
            mResultList!!.add(sub)
        }
        return mResultList as ArrayList<List<Entry>>
    }
 
    override fun onFinishInflate() {
        super.onFinishInflate()
        //初始化ViewPager (入口列表)
        mIndicatiorWidth = dip2px(IND_WIDTH_SIZE).toFloat()
        val llContent = LinearLayout(mContext)
        llContent.orientation = LinearLayout.VERTICAL
        val params = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
        mViewPager = CustomViewPager(mContext!!)
        mViewPager?.layoutParams = params
        llContent.addView(mViewPager)
        //初始化指示器容器
        mIndecatorLayout = LinearLayout(mContext)
        params.bottomMargin = 28
        mIndecatorLayout?.layoutParams = params
        mIndecatorLayout?.orientation = LinearLayout.HORIZONTAL
        llContent.addView(mIndecatorLayout)
        mViewPager?.addOnPageChangeListener(this)
        addView(llContent)
    }
 
    /**
     * 计算出页面的数量
     */
    private fun pageNum(): Int {
        mCount = if (mLists?.size!! % mPageSize != 0 && mLists?.size!! / mPageSize < 1)
            1
        else if (mLists?.size!! % mPageSize != 0 && mLists?.size!! / mPageSize >= 1)
            mLists?.size!! / mPageSize + 1
        else
            mLists?.size!! / mPageSize
        return mCount
    }
 
    override fun onPageScrollStateChanged(state: Int) {
    }
 
    override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
    }
 
    override fun onPageSelected(position: Int) {
        mCurrentPos = position
        mIndecatorLayout?.getChildAt(mPrePosition % mCount)?.isEnabled = false
        mIndecatorLayout?.getChildAt(mCurrentPos % mCount)?.isEnabled = true
        mPrePosition = mCurrentPos
    }
 
    /**
     * 根据手机的分辨率从dip的单位转为px(像素)
     */
    fun dip2px(dpValue: Float): Int {
        val scale: Float = mContext!!.resources.displayMetrics.density
        return (dpValue * scale + 0.5f).toInt()
    }
 
    /**
     * 导航ViewPager的适配器,向ViewPager的每一个页中添加一个GridView
     */
    inner class MyEntryAdapter(itemView: MutableList<View>) : PagerAdapter() {
 
        private var listItem: MutableList<View>? = itemView
 
        override fun isViewFromObject(view: View, `object`: Any): Boolean {
            return view == `object`
        }
 
        override fun getCount(): Int {
            return mCount
        }
 
        override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
            container.removeView(`object` as View?)
        }
 
        override fun instantiateItem(container: ViewGroup, position: Int): Any {
            //向viewpager每一页中添加一个gridView布局
            for (item in 0 until mCount) {
                val gridView = CustomGridView(mContext!!)
                gridView.numColumns = mColumNum
                gridView.gravity = Gravity.CENTER
                gridView.setPadding(2, 2, 2, 0)
                listItem?.add(gridView)
                mMyGridViewAdapter = MyGridViewAdapter(mContext, mResultList?.get(item), 0, mPageSize)
                gridView.adapter = mMyGridViewAdapter
            }
            container.addView(listItem?.get(position))
            return listItem?.get(position)!!
        }
    }
 
    /**
     * 导航gridView的适配器,向girdView的每一项中添加信息
     *  index参数 页数下标,表示第几页,从0开始
     *  mPagerSize参数 每页显示的最大的数量
     */
    inner class MyGridViewAdapter(var context: Context?, var lists: List<Entry>?, var index: Int, var mPagerSize: Int) : BaseAdapter() {
 
        override fun getView(p0: Int, p1: View?, p2: ViewGroup?): View {
            return addGridViewChildLayout(p1, p0)
        }
 
        override fun getItem(p0: Int): Any {
            return lists?.get(p0 + index * mPagerSize)!!
        }
 
        override fun getItemId(p0: Int): Long {
            return (p0 + index * mPagerSize).toLong()
        }
 
        override fun getCount(): Int {
            return if ((lists?.size ?: 0) > (index + 1) * mPagerSize) {
                mPagerSize
            } else {
                ((lists?.size ?: 0).minus(index * mPagerSize))
            }
        }
 
        /**
         * 动态创建gridView的子布局
         */
        private fun addGridViewChildLayout(view: View?, position: Int): View {
            val any = LinearLayout(mContext)
            val params: AbsListView.LayoutParams = GridView@ AbsListView.LayoutParams(GridView@ AbsListView.LayoutParams.MATCH_PARENT, GridView@ AbsListView.LayoutParams.MATCH_PARENT)
            any.orientation = LinearLayout.VERTICAL
            any.layoutParams = params
            any.setPadding(0, this@EntryListView.dip2px(10f), 0, 0)
            any.gravity = Gravity.CENTER
            val imgParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            val tvParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
            imgParams.gravity = Gravity.CENTER
            imgParams.width = this@EntryListView.dip2px(mIconSize)
            imgParams.height = this@EntryListView.dip2px(mIconSize)
            val img = ImageView(context)
            img.scaleType = ImageView.ScaleType.FIT_XY
            img.layoutParams = imgParams
            any.addView(img)
            val textView = TextView(context)
            textView.textSize = mTextSize
            textView.setTextColor(resources.getColor(R.color.colorPrimary))
            textView.setPadding(0, 20, 0, 0)
            textView.layoutParams = tvParams
            any.addView(textView)
            Glide.with(context!!).load(lists?.get(position)?.icon).into(img)
            textView.text = lists?.get(position)?.title
            return view ?: any
        }
    }
 
    /**
     * 定义ViewPager滑动效果
     */
    class MyPageTransformer : ViewPager.PageTransformer {
        override fun transformPage(page: View, position: Float) {
            val normalize = Math.abs(Math.abs(position) - 1)
            page.alpha = normalize
        }
    }
 
    /**
     * 自定义ViewPager,计算ViewPager高度
     */
    class CustomViewPager(context: Context) : ViewPager(context) {
 
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            var height = 0
            for (item in 0 until childCount) {
                val child = getChildAt(item)
                child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
                val h = child.measuredHeight
                if (h > height)
                    height = h
            }
            val expandSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
            super.onMeasure(widthMeasureSpec, expandSpec)
        }
    }
 
    /**
     * 自定义GridView,计算GridView高度
     */
    class CustomGridView(context: Context) : GridView(context) {
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            val expandSpec = MeasureSpec.makeMeasureSpec(Int.MAX_VALUE.shr(2), MeasureSpec.AT_MOST)
            super.onMeasure(widthMeasureSpec, expandSpec)
        }
    }
}
相关文章
|
5月前
|
XML Android开发 数据安全/隐私保护
10. 【Android教程】网格布局 GridLayout
10. 【Android教程】网格布局 GridLayout
306 1
|
Android开发
flutter中实现仿Android端的onResume和onPause方法
flutter中实现仿Android端的onResume和onPause方法
|
4月前
|
Android开发 Kotlin
kotlin开发安卓app,如何让布局自适应系统传统导航和全面屏导航
使用`navigationBarsPadding()`修饰符实现界面自适应,自动处理底部导航栏的内边距,再加上`.padding(bottom = 10.dp)`设定内容与屏幕底部的距离,以完成全面的布局适配。示例代码采用Kotlin。
130 15
|
5月前
|
前端开发 API Android开发
26. 【Android教程】网格视图 GridView
26. 【Android教程】网格视图 GridView
81 2
|
6月前
|
Android开发
Android Studio入门之常用布局的讲解以及实战(附源码 超详细必看)(包括线性布局、权重布局、相对布局、网格布局、滚动视图 )
Android Studio入门之常用布局的讲解以及实战(附源码 超详细必看)(包括线性布局、权重布局、相对布局、网格布局、滚动视图 )
595 0
|
6月前
|
Java Android开发
Android 导航方式切换
Android 导航方式切换
137 1
|
6月前
|
XML 数据可视化 Java
Android布局——线性布局、相对布局、帧布局、表格布局、网格布局、约束布局
Android布局——线性布局、相对布局、帧布局、表格布局、网格布局、约束布局
129 1
|
6月前
|
Android开发
Android布局——帧布局、表格布局、网格布局
Android布局——帧布局、表格布局、网格布局
|
6月前
|
Android开发
【Android 从入门到出门】第四章:现代Android开发中的导航
【Android 从入门到出门】第四章:现代Android开发中的导航
43 2
【Android 从入门到出门】第四章:现代Android开发中的导航
|
6月前
|
Java 定位技术 Android开发
【Android App】利用腾讯地图获取地点信息和规划导航线路讲解及实战(附源码和演示视频 超详细必看)
【Android App】利用腾讯地图获取地点信息和规划导航线路讲解及实战(附源码和演示视频 超详细必看)
386 1
下一篇
无影云桌面