この前の人 のように、GridViewアイテム間に不要なオーバーラップがあります:
右端の列を除くすべての列のテキストに注意してください。
前の質問と違うのは、私が一定の行の高さを望まないということです。画面のスペースを効率的に使用するために、行の高さをに変えて、各行の最も高いコンテンツに対応させたい。
GridViewのソース (信頼できるコピーではありませんが、kernel.orgはまだダウンしています)を見ると、fillDown()およびmakeRow()で、最後に表示されたビューが「参照ビュー」であることがわかります。 :行の高さは、最も高いものではなく、そのビューの高さから設定されます。 これは、右端の列が大丈夫な理由を説明します。残念ながら、GridViewは継承によってこれを修正するための適切な設定ではありません。関連するすべてのフィールドとメソッドはプライベートです。
だから、私は「クローンと所有」という使い古された肥大化した道を取る前に、ここに欠けているトリックがありますか? TableLayout、しかし、それは私がnumColumns="auto_fit"
を自分で実装することを要求します(たとえば、電話画面に1つの長い列だけが必要なため)、また、それは本来あるべきように感じるAdapterViewでもありません。
Edit:実際、ここではclone and ownは実用的ではありません。 GridViewは、親クラスと兄弟クラスのアクセスできない部分に依存し、少なくとも6000行のコード(AbsListView、AdapterViewなど)をインポートします。
私は非常に多くの研究を行いましたが、不完全な答えを見つけた、またはソリューションで何が起こっているのかを理解するのが困難でしたが、最終的に適切な説明に完全に適合する答えを見つけました。
私の問題は、gridviewアイテムを適切に高さに合わせることでした。この Grid-view
すべてのビューが同じ高さのとき、うまく機能しました。ただし、ビューの高さが異なる場合、グリッドは期待どおりに動作しません。ビューは互いに重なり、an-aesthetically
心地よいグリッド。
ここ Solution XMLレイアウトでこのクラスを使用しました。
私はこのソリューションを使用しましたが、これは非常にうまく機能しています。ありがとうございます。--Abhishek Mittal
Chrisからの情報に基づいて、他のGridViewアイテムの高さを決定するときに、ネイティブのGridViewで使用される参照ビューを利用して、この回避策を使用しました。
このGridViewItemContainerカスタムクラスを作成しました。
/**
* This class makes sure that all items in a GridView row are of the same height.
* (Could extend FrameLayout, LinearLayout etc as well, RelativeLayout was just my choice here)
* @author Anton Spaans
*
*/
public class GridViewItemContainer extends RelativeLayout {
private View[] viewsInRow;
public GridViewItemContainer(Context context) {
super(context);
}
public GridViewItemContainer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public GridViewItemContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setViewsInRow(View[] viewsInRow) {
if (viewsInRow != null) {
if (this.viewsInRow == null) {
this.viewsInRow = Arrays.copyOf(viewsInRow, viewsInRow.length);
}
else {
System.arraycopy(viewsInRow, 0, this.viewsInRow, 0, viewsInRow.length);
}
}
else if (this.viewsInRow != null){
Arrays.fill(this.viewsInRow, null);
}
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (viewsInRow == null) {
return;
}
int measuredHeight = getMeasuredHeight();
int maxHeight = measuredHeight;
for (View siblingInRow : viewsInRow) {
if (siblingInRow != null) {
maxHeight = Math.max(maxHeight, siblingInRow.getMeasuredHeight());
}
}
if (maxHeight == measuredHeight) {
return;
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
switch(heightMode) {
case MeasureSpec.AT_MOST:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(maxHeight, heightSize), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
break;
case MeasureSpec.EXACTLY:
// No debate here. Final measuring already took place. That's it.
break;
case MeasureSpec.UNSPECIFIED:
heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
break;
}
}
アダプターのgetViewメソッドで、convertViewを新しいGridViewItemContainerの子としてラップするか、これをアイテムレイアウトの最上位XML要素にします。
// convertView has been just been inflated or came from getView parameter.
if (!(convertView instanceof GridViewItemContainer)) {
ViewGroup container = new GridViewItemContainer(inflater.getContext());
// If you have tags, move them to the new top element. E.g.:
container.setTag(convertView.getTag());
convertView.setTag(null);
container.addView(convertView);
convertView = container;
}
...
...
viewsInRow[position % numColumns] = convertView;
GridViewItemContainer referenceView = (GridViewItemContainer)convertView;
if ((position % numColumns == (numColumns-1)) || (position == getCount()-1)) {
referenceView.setViewsInRow(viewsInRow);
}
else {
referenceView.setViewsInRow(null);
}
ここで、numColumnsはGridViewの列数で、「viewsInRow」は「position」が存在する現在の行のビューのリストです。
GridViewまたはListViewを RecyclerView に変換すると、この問題は発生しません。また、カスタムGridViewクラスを作成する必要はありません。