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

}
相關文章
相關標籤/搜索