无意中打开了一年前做过的一个android应用的代码,看到里面实现的一个小功能点(如题),现写篇文章做个笔记。当时面临的问题是,在旋转屏幕的时候需要让gridview的列数与宽度能自适应屏幕宽度,每个单元格之间还需要保留一定的间距。因为每款手机的屏幕宽度不都相同,我们在指定了单元格的宽度与间距之后,并不能确定每行中所能容纳的单元格数量,这个数量必须在运行时通过计算得出,同样,我们设置的单元格宽度和间距不能保证刚好容纳在屏幕宽度内,为了解决这个问题,设计了一个简单的算法,首先需要预先指定单元格的宽度和间距,然后根据屏幕宽度通过计算得出调整后的单元格宽度与每行所能容纳的单元格数量,对于每个单元格来说,调整后宽度与初始宽度的误差小于:单元格初始宽度 / ( 2 * 调整后每行单元格数量 ),当单元格宽度小于屏幕宽度时极端情况下的最大误差为:单元格初始宽度 / 4。经过试验,很好的解决了自适应的问题。

算法流程如下:

  1. 指定单元格初始宽度值width和间距padding,并获取屏幕宽度值
  2. 计算屏幕中是否刚好能容纳下整数个单元格,如果能,计算出单元格数量,然后直接跳到第6步,否则继续下一步
  3. 计算单元格总宽度超出屏幕的宽度值,如果超出的宽度值小于单元格初始宽度值的一半,继续下一步,否则跳到第5步
  4. 计算单元格数量,并将超出屏幕的宽度值按单元格数量进行平分(负值),添加到每个单元格上,即:cellWidth = cellWidth - avgSpace,然后跳到第6步
  5. 计算单元格数量,并将单元格宽度减去超出屏幕宽度后的值按单元格数量进行平分(正值),添加到每个单元格上,即:cellWidth = cellWidth + avgSpace
  6. 根据单元格数量算出总间距,将总间距平分(负值),添加到每个单元格上,即:cellWidth = cellWidth - avgPadding
  7. 最后得出的就是自适应单元格数量与宽度

  这样我们就实现了一个小算法,通过指定列间距(不需要可设为零)和初始列宽(这个值只是一个大概宽度),就能在运行时根据手机屏幕的宽度自动计算出屏幕可容纳的精确列宽和列数,从而屏蔽了众多手机屏幕尺寸不同的问题,达到了自适应的目的,该方法也可适用于其他类似的场景。

下图是分析问题时画得草图:

  ①是超出屏幕的宽度小于单元格初始宽度的一半,对应算法流程的第3、4、6步

  ②是超出屏幕的宽度大于单元格初始宽度的一半,对应算法流程的第3、5、6步

  将计算单元格宽度的代码放到onCreateView方法中,这样每次旋转屏幕时就会自动调整gridview中每行的单元格数和宽度,使其刚好容纳在屏幕宽度内。

  下面是运行截图(仔细看会发现竖屏和横屏中的单元格宽度是不一样的,自适应的结果):

代码如下(省去了部分不必要的代码):

public class FragmentAllBushou extends Fragment {

    GridView gridView = null;

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { WindowManager manger = getActivity().getWindowManager();
Display display = manager.getDefaultDisplay(); //屏幕高度
int screenHeight = display.getHeight();
//屏幕宽度
int screenWidth = display.getWidth(); gridView = new GridView(getActivity());
ColumnInfo colInfo = calculateColumnWidthAndCountInRow(screenWidth, 100,2);
int rowNum = cursor.getCount()%colInfo.countInRow == 0 ? cursor.getCount()/colInfo.countInRow:cursor.getCount()/colInfo.countInRow+1;
gridView.setLayoutParams(new LayoutParams(screenWidth,rowNum*colInfo.width+(rowNum-1)*2));
gridView.setNumColumns(colInfo.countInRow);
gridView.setGravity(Gravity.CENTER);
gridView.setHorizontalSpacing(2);
gridView.setVerticalSpacing(2);
gridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
} //存放计算后的单元格相关信息
class ColumnInfo{
//单元格宽度
public int width = 0;
//每行所能容纳的单元格数量
public int countInRow = 0;
} /**
* 根据手机屏幕宽度,计算gridview每个单元格的宽度
* @param screenWidth 屏幕宽度
* @param width 单元格预设宽度
* @param padding 单元格间距
* @return
*/
private ColumnInfo calculateColumnWidthAndCountInRow(int screenWidth,int width,int padding){
ColumnInfo colInfo = new ColumnInfo();
int colCount = 0;
//判断屏幕是否刚好能容纳下整数个单元格,若不能,则将多出的宽度保存到space中
int space = screenWidth % width; if( space == 0 ){ //正好容纳下
colCount = screenWidth / width;
}else if( space >= ( width / 2 ) ){ //多出的宽度大于单元格宽度的一半时,则去除最后一个单元格,将其所占的宽度平分并增加到其他每个单元格中
colCount = screenWidth / width;
space = width - space;
width = width + space / colCount;
}else{ //多出的宽度小于单元格宽度的一半时,则将多出的宽度平分,并让每个单元格减去平分后的宽度
colCount = screenWidth / width + 1;
width = width - space / colCount;
} colInfo.countInRow = colCount;
//计算出每行的间距总宽度,并根据单元格的数量重新调整单元格的宽度
colInfo.width = width - (( colCount + 1 ) * padding ) / colCount; return colInfo;
} }

android手机旋转屏幕时让GridView的列数与列宽度自适应的更多相关文章

  1. Android 禁止屏幕旋转 & 旋转屏幕时保持Activity内容

    Android 禁止屏幕旋转 & 旋转屏幕时保持Activity内容   1.在应用中固定屏幕方向.        在AndroidManifest.xml的activity中加入:     ...

  2. Android中动态设置GridView的列数、列宽和行高

    在使用GridView时我们知道,列数是可以通过设计时的属性来设置的,列的宽度则是根据列数和GridView的宽度计算出来的.但是有些时候我们想实现列数是动态改变的效果,即列的宽度保持某个值,列的数量 ...

  3. Android开发 旋转屏幕导致Activity重建解决方法(转)

     文章来源:http://www.jb51.net/article/31833.htm Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何“ ...

  4. [Selenium] Android 中旋转屏幕,触摸,滚动

    package com.learingselenium.android; import junit.framework.TestCase import org.openqa.selenium.Rota ...

  5. android手机旋转方向识别

    private OrientationEventListener mOrientationListener; private String TAG = "MainActivity" ...

  6. 获取android手机的屏幕分辨率 android开发

    /** * 获取屏幕分辨率 */ private void getResolution() { // TODO Auto-generated method stub Display display = ...

  7. 旋转屏幕时,假如自定义的xib大小变了,可能是这个属性没有修改

    虽然xib内部启用了自动布局,但是当xib放入外界,xib自身的autoresizing是存在的

  8. Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案

    一.概述 运行时变更就是设备在运行时发生变化(例如屏幕旋转.键盘可用性及语言).发生这些变化,Android会重启Activity,这时就需要保存activity的状态及与activity相关的任务, ...

  9. Android手机怎样录制屏幕及转GIF

    有时候我们须要录制Android 手机的屏幕,比方写了一个Demo应用,须要公布到博客和微博上. 例如以下是我录制转GIF的效果图 对于Android4.4的上的手机,系统自带了一个命令screenr ...

随机推荐

  1. C#中Length和Count的区别(个人观点)

    这篇文章将会很短...短到比你的JJ还短,当然开玩笑了.网上有说过Length和count的区别,都是很含糊的,我没有发现有 文章说得比较透彻的,所以,虽然这篇文章很短,我还是希望能留在首页,听听大家 ...

  2. Unity3D框架插件uFrame实践记录(一)

    1.概览 uFrame是提供给Unity3D开发者使用的一个框架插件,它本身模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了Controller部分).因为用于Unity3D,所以它 ...

  3. Autofac - 属性注入

    属性注入不同于通过构造函数方式传入参数. 这里是通过注入的方式, 在类创建完毕之后, 资源释放之前, 给属性赋值. 这里, 我重新弄一些类来演示这一篇吧. public class ClassA { ...

  4. [Hadoop in Action] 第5章 高阶MapReduce

    链接多个MapReduce作业 执行多个数据集的联结 生成Bloom filter   1.链接MapReduce作业   [顺序链接MapReduce作业]   mapreduce-1 | mapr ...

  5. Linux监控工具介绍系列——vmstat

      说来惭愧,玩Linux这么久了,居然没有玩转vmstat这个命令,对很多指标的具体意义都有点模糊不清,花了点时间好好学习.整理一下这个命令的相关资料.因为这个命令确实比较重要,而且频繁用到. 命令 ...

  6. ASP.NET Aries DataGrid 配置表头说明文档

    DataGrid 配置表头 字段 中文 说明 Field 字段 注意:mg_ 开头的字段为层级表头 Title 列称 OrderNum 序号 显示的顺序(冻结和非冻结列是两个组的序号) Width 列 ...

  7. Android(3)—Mono For Android App版本自动更新(2)

    0.前言 这篇博文是上一篇的延续,主要是修改上一个版中的BUG和优化一些待完善的项,也算是结贴,当然还有需要完善的,等日后项目中用到的时候再单独写出来吧,本篇主要写升级改进的部分: 改进1.修复[BU ...

  8. 为什么说每个程序员都应该刷几道LeetCode?

    2015年即将过去,最近在回顾和总结过去一年的工作经历,发现自己并不能算是一名合格的程序员. Google某前员工Lucida在文章<白板编程访谈——Why,What,How>当中写道: ...

  9. ASP.NET Web API 控制器创建过程(一)

    ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...

  10. 在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView

    背景 在前一篇文章<[初学者指南]在ASP.NET MVC 5中创建GridView>中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web ...