android手机旋转屏幕时让GridView的列数与列宽度自适应

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

算法流程以下:算法

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

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

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

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

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

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

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

代码以下(省去了部分没必要要的代码):get

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;
    }

}
相关文章
相关标签/搜索