当前位置: 首页 > news >正文

深圳.网站建设一个网站怎么做流量统计

深圳.网站建设,一个网站怎么做流量统计,如何自己开个网站平台,如何让网站自适应前言 如果GridLayoutManager使用item的布局都是wrap_cotent 那么会在布局更改时会出现一些出人意料的情况。#xff08;本文完全不具备可读性和说教性#xff0c;仅为博主方便查找问题#xff09; 布局item: !--layout_item.xml-- ?xml version1.0本文完全不具备可读性和说教性仅为博主方便查找问题 布局item: !--layout_item.xml-- ?xml version1.0 encodingutf-8? com.vb.rerdemo.MyConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:layout_marginTop10dpandroid:background#f0fcom.google.android.material.card.MaterialCardViewandroid:layout_widthmatch_parentapp:layout_constraintTop_toTopOfparentapp:cardCornerRadius10dpapp:cardBackgroundColor#908000android:layout_height240dpTextViewandroid:idid/tvandroid:layout_gravitycenterandroid:layout_widthwrap_contentandroid:texthello worldandroid:layout_heightwrap_contentapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent //com.google.android.material.card.MaterialCardView /com.vb.rerdemo.MyConstraintLayout//LastGapDecoration.kt //给最后一行的item添加一个高度 class LastGapDecoration : ItemDecoration() {override fun getItemOffsets(outRect: Rect,view: View,parent: RecyclerView,state: RecyclerView.State) {super.getItemOffsets(outRect, view, parent, state)super.getItemOffsets(outRect, view, parent, state)val itemPosition parent.getChildAdapterPosition(view)val gridLayoutManager parent.layoutManager as? GridLayoutManager ?: returnval spanCount gridLayoutManager.spanCountval itemCount gridLayoutManager.itemCountif (spanCount 0) {return}val lastRowItemCount itemCount % spanCountval lastRow isLastRow(itemPosition, itemCount, spanCount, lastRowItemCount)Log.d(fmy,lastRow ${lastRow} itemPosition ${itemPosition} lastRowItemCount ${lastRowItemCount} itemCount ${itemCount} viewid ${view.hashCode()})if (lastRow) {outRect.bottom ScreenUtil.dp2px(40f,App.myapp)} else {outRect.bottom 0}}private fun isLastRow(itemPosition: Int,itemCount: Int,spanCount: Int,lastRowItemCount: Int): Boolean {// 如果最后一行的数量不足一整行则直接判断位置if (lastRowItemCount ! 0 itemPosition itemCount - lastRowItemCount) {return true}// 如果最后一行的数量足够一整行则需要计算val rowIndex itemPosition / spanCountval totalRow ceil(itemCount.toDouble() / spanCount).toInt()return rowIndex totalRow - 1} }当我们填充6个布局后的效果 红色区域和4和5之间的间距通过LastGapDecoration完成。 此时我们移除3后 根本原因在于GridLayoutManager#layoutChunk函数中 public class GridLayoutManager extends LinearLayoutManager {View[] mSet;//layoutChunk 每次调用只拿取当前行view进行对比计算//比如GridLayoutManager一行两个那么每次会拿取每行的对应view进行计算void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,LayoutState layoutState, LayoutChunkResult result) {int count 0;while (count mSpanCount layoutState.hasMore(state) remainingSpan 0) {//略... 经过一些的计算mSet放入本次要进行摆放的view//count 一般为GridLayoutManager的spanCount数量mSet[count] view;count;}//maxSize是指在本次layoutChunk中所有view里面最大的高度数据。包含view自身和ItemDecorations得到的int maxSize 0;// we should assign spans before item decor offsets are calculatedfor (int i 0; i count; i) {//计算ItemDecorationscalculateItemDecorationsForChild(view, mDecorInsets);//调用measure计算view宽高 核心//核心代码点注意这里调用子view的measure参数为layoutparameter高度//我们把这里称为操作AmeasureChild(view, otherDirSpecMode, false);//核心代码点这里这里会得到这个view的宽高和ItemDecorations填充的高度和final int size mOrientationHelper.getDecoratedMeasurement(view);//核心代码点 记录最大数值if (size maxSize) {maxSize size;}}//我们把这里称为操作B//取出当前行中的所有view。保证行高度一致for (int i 0; i count; i) {final View view mSet[i];if (mOrientationHelper.getDecoratedMeasurement(view) ! maxSize) {final LayoutParams lp (LayoutParams) view.getLayoutParams();final Rect decorInsets lp.mDecorInsets;final int verticalInsets decorInsets.top decorInsets.bottom lp.topMargin lp.bottomMargin;final int horizontalInsets decorInsets.left decorInsets.right lp.leftMargin lp.rightMargin;final int totalSpaceInOther getSpaceForSpanRange(lp.mSpanIndex, lp.mSpanSize);final int wSpec;final int hSpec;if (mOrientation VERTICAL) {wSpec getChildMeasureSpec(totalSpaceInOther, View.MeasureSpec.EXACTLY,horizontalInsets, lp.width, false);//核心代码点 这里会强制当前行所有view的高度与最高的view保持一致。 hSpec View.MeasureSpec.makeMeasureSpec(maxSize - verticalInsets,View.MeasureSpec.EXACTLY);} else {//略}//执行测量measureChildWithDecorationsAndMargin(view, wSpec, hSpec, true);}} } } 上面的代码可以总结为 取出当前的所有view对所有view执行一次高度测量并记录当前最高的view数据在此执行一次测量保证当前行的所有view高度一致 我们重点再看一眼measureChild函数 private void measureChild(View view, int otherDirParentSpecMode, boolean alreadyMeasured) {final LayoutParams lp (LayoutParams) view.getLayoutParams();final Rect decorInsets lp.mDecorInsets;final int verticalInsets decorInsets.top decorInsets.bottom lp.topMargin lp.bottomMargin;final int horizontalInsets decorInsets.left decorInsets.right lp.leftMargin lp.rightMargin;final int availableSpaceInOther getSpaceForSpanRange(lp.mSpanIndex, lp.mSpanSize);final int wSpec;final int hSpec;if (mOrientation VERTICAL) {wSpec getChildMeasureSpec(availableSpaceInOther, otherDirParentSpecMode,horizontalInsets, lp.width, false);//mOrientationHelper.getTotalSpace()可以先忽略//verticalInsets 就是decorate中的高度和一些margin等数值//lp.height如果是wrapcontent那么一返回高度为0的MeasureSpec.UNSPECIFIED//lp.height如果不是wrapcontent那么一返回高度为父亲高度减去verticalInsets的MeasureSpec.EXACTLY//lp.height如果是一个明确数值那么一返回高度为设置的高度的MeasureSpec.EXACTLY//总结getChildMeasureSpec传入布局参数高度和decorate高度hSpec getChildMeasureSpec(mOrientationHelper.getTotalSpace(), getHeightMode(),verticalInsets, lp.height, true);} else {//略}//透传给子view测量measureChildWithDecorationsAndMargin(view, wSpec, hSpec, alreadyMeasured);}measureChildWithDecorationsAndMargin函数会根据必要性确定是否要执行子view的测量操作。 private void measureChildWithDecorationsAndMargin(View child, int widthSpec, int heightSpec,boolean alreadyMeasured) {RecyclerView.LayoutParams lp (RecyclerView.LayoutParams) child.getLayoutParams();final boolean measure;if (alreadyMeasured) {measure shouldReMeasureChild(child, widthSpec, heightSpec, lp);} else {measure shouldMeasureChild(child, widthSpec, heightSpec, lp);}//根据情况是否执行if (measure) {child.measure(widthSpec, heightSpec);}}boolean shouldReMeasureChild(View child, int widthSpec, int heightSpec, LayoutParams lp) {return !mMeasurementCacheEnabled|| !isMeasurementUpToDate(child.getMeasuredWidth(), widthSpec, lp.width)|| !isMeasurementUpToDate(child.getMeasuredHeight(), heightSpec, lp.height);}boolean shouldMeasureChild(View child, int widthSpec, int heightSpec, LayoutParams lp) {return child.isLayoutRequested()|| !mMeasurementCacheEnabled|| !isMeasurementUpToDate(child.getWidth(), widthSpec, lp.width)|| !isMeasurementUpToDate(child.getHeight(), heightSpec, lp.height);} shouldReMeasureChild可以总结为 如果没有开启缓存那么一定执行测绘如果开启了缓存那么判断之前是否执行过相同参数测量 在了解上面的信息我们可以总结一下流程发现问题 我们假设假设wrapcotent计算的高度为50 decorate插入的高度为10 插入0时0执行操作A不执行操作B 插入1时 0和1同时执行操作A不执行操作B。0由于之前测绘过不会触发onmeasure。 1触发onmeasure 插入2时 0和1同时执行操作A,不执行操作B 0和1不会触发onmeasure。 2执行操作A并触发onmeasure 插入3时 0和1同时执行操作A,不执行操作B 0和1不会触发onmeasure。 3和2执行操作A 2不会触发onmeasure3触发onmeasure。 移除1时 0 和 1 同时执行操作A 0 和1不会触发onmeasure操作B不会执行(虽然1被移除 但是由于预布局存在还需要进行一次比较)2 和 3 同时执行操作A 2 和3不会触发onmeasure. 由于2移动第一行不会有decorate高度因此2执行操作B并触发onmeasure。2 高度为60移除后2和3虽然不在一行但需要执行预布局0和2进行同时执行操作A 0 和2不会触发onmeasure同时0会被执行操作B把高度填充到60. 虽然2没有decorate的高度 但是上一次预布局引起了2高度错误3 同时执行操作A 不会触发onmeasure 不会触发操作B 解决方案 val manager GridLayoutManager(this, 2) manager.isMeasurementCacheEnabled false
http://www.pierceye.com/news/306826/

相关文章:

  • 蓝杉网站建设公司贵阳网站建设公司排名
  • 苏州专业高端网站建设机构建网站公司下载快手
  • 中堂仿做网站个人网站设计论文道客巴巴
  • 怎么用ps做网站效果图24什么网站建设
  • 网站开发技术有网站建设方案 pdf
  • 网站建设教程浩森宇特福州医院网站建设公司
  • 怎样在网站上做超链接网站商城是用什么框架做的
  • 网站建设增城wordpress新文章类型
  • 广州市招投标中心官网上海网站关键词优化
  • 很多网站开发没有框架如何制作的长沙旅游景点大全排名
  • 云南网站推广的目的做动画的网站有哪些
  • 网站建设公司在哪里找资源模拟建设网站
  • 如何盗用网站模板哈尔滨公告
  • 管理咨询网站焦作专业做网站公司哪家好
  • 在国内做跨境电商怎么上外国网站网站不收录
  • 网站介绍ppt怎么做屏蔽网站ip
  • it公论 是建立在什么网站wordpress搬迁数据库连接失败
  • 南县建设局网站营销型网站开发流程包括
  • 有关应用网站申请免费网站空间
  • 二手书交易网站开发现状营销型网站建设推荐乐云seo
  • 山西网站建设怎么样seo优化网站多少钱
  • 网站建设设计模板磁力链最佳的搜索引擎
  • 单位外部网站建设价格哪些网站可以做视频直播
  • 广州黄埔网站建设公司国外做调灵风暴的网站
  • 珠海附近交友平台软件广州网站优化推广方案
  • cgi做网站如何将网站加入百度图 推广
  • 小贷做网站深圳手机app软件开发
  • 上海平台网站建设费用页面模板不存在怎么办
  • 西安网站排名公司上海工商网查询官网
  • 网站建设协调机制建网站 可以看到访客吗