2013年11月4日月曜日

[Android] GridView で列数を固定する。

GridView は列数を numColumns で指定すると、 GridView の横幅に応じて セルの幅を自動的に決めてくれる。

しかし、縦幅はセルに指定したアイテムの縦幅が採用されるので、 行数も固定して GridView を綺麗に固定するには GridView のサイズに応じて、アイテムの縦幅を調整する必要がある。


高さ設定のための独自 Adapter の実装


GridView に設定する ArrayAdapter をカスタマイズして、 getView で各ビューに GridView の高さを 行数で割った値を設定することで 各行の高さを調整する。

public class MainActivity extends Activity {
  private static final int ROW = 7;
  private static final int COLUMN = 5;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

    ArrayList<String> list = new ArrayList<String>();
    for (int i=1; i<=ROW*COLUMN; i++) {
        list.add(String.valueOf(i));
    }

    MyAdapter adapter = new MyAdapter(
        getApplicationContext(), android.R.layout.simple_list_item_1, 
        list);

      GridView gridView = (GridView) findViewById(R.id.gridView1);
      gridView.setAdapter(adapter);  
  }
  ...


GridView には、高さ調整をするための MyAdapter をアダプターとして与えておく。
MyAdapter はまずはこんな感じで実装する。
  ... 
  public class MyAdapter extends ArrayAdapter<String> {
    public MyAdapter(Context context, int layoutId, List<String> objects) { 
      super(context, layoutId, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      if (convertView == null) {
        TextView textView =  new TextView(MainActivity.this);
        textView.setText(this.getItem(position));
        textView.setBackgroundColor(Color.parseColor(
            position % 2 == 1 ? "green" : "blue"));

        int parentHeight = parent.getHeight();
        textView.setHeight(parentHeight / ROW);
        return textView;
      }
      return convertView;
    }
  }
}

しかし、position == 0 になる最初の呼び出しの時には、 parent.getHeight() の値が 0 になってしまい、最初の TextView の高さが 0 になってしまう。


parent.getHeight() == 0 の対策


最初の呼び出しで parent.getHeight() が0になる対策として、 parent.getHeight() になった TextView を保持しておいて、 parent.getHeight() で正しい値が取得できるようになった時に、 以前のTextView に改めて正しい高さを設定するようにする。

  ... 
  public class MyAdapter extends ArrayAdapter<String> {
    private ArrayList m_unstableView = new ArrayList<TextView>();

    public MyAdapter(Context context, int layoutId, List objects) { 
      super(context, layoutId, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      if (convertView == null) {
        TextView textView =  new TextView(MainActivity.this);
        textView.setText(this.getItem(position));
        textView.setBackgroundColor(Color.parseColor(
            position % 2 == 1 ? "green" : "blue"));

        int parentHeight = parent.getHeight();
        textView.setHeight(parentHeight / ROW);
        if (parentHeight != 0 && m_unstableView.size() > 0) {
          for (TextView v : m_unstableView) {
            v.setHeight(parentHeight / ROW);
          }
          m_unstableView.clear();
        } else {
         m_unstableView.add(textView);
        }
        return textView;
      }
      return convertView;
    }
  }
}


これで以下のような表示になった。



解決策としては強引な気がするし、もっと適切なやり方があるような気がするが、 とりあえずはこれで目的の表示にはなった。


0 件のコメント:

コメントを投稿