GridViewのチェックボックスを使用して、動的に成長する文字列のリストを表示しようとしています。GridViewはTableLayoutにあります。
これらの「チェックボックス」文字列を連続して表示できます。ユーザーがGridViewに新しい文字列を動的に追加できるようにすると、問題が発生します。
文字列のリストを受け取るカスタムアダプターを作成しました。 n個の文字列があるとします。アダプターは、アイテム数に対して「n + 1」を返します。 getViewでは、次を返します。
ここまでは順調ですね。 [+]ボタンをクリックすると、空の文字列が文字列のリストに追加され、アダプターでnotifyDataSetChangedが呼び出されます。
GridViewは、もう1つのアイテムで再描画します。ただし、元の高さを維持し、垂直スクロールバーを作成します。 GridViewの高さを拡張したい(つまり、画面上のスペースをより多く使用してすべてのアイテムを表示したい)。
画面をTableLayoutではなく垂直のLinearLayoutに変更しようとしましたが、結果は同じです。
画面のレイアウトは次のとおりです。
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:scrollbars="none">
<LinearLayout
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
>
<!-- other lines omitted -->
<LinearLayout Android:layout_width="fill_parent"
Android:layout_height="wrap_content" >
<TextView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/wine_rack_explanation"
Android:layout_gravity="center_vertical" />
<GridView
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:id="@+id/gvRack"
Android:columnWidth="90dp"
Android:numColumns="auto_fit" />
</LinearLayout>
<!-- other lines omitted -->
</LinearLayout>
</ScrollView>
アダプタのチェックボックス+文字列アイテムは、次のように定義されます。
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="horizontal"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content">
<CheckBox Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:id="@+id/cbCoordinate"
Android:checked="true"
/>
<EditText Android:id="@+id/txtCoordinate"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
</LinearLayout>
「+」ボタン項目は次のように定義されます。
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="horizontal"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content">
<Button Android:id="@+id/btnAddBottle"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@string/add_bottle_caption" />
</LinearLayout>
アイテムが追加された後、GridViewでinvalidateまたはinvalideViewsを呼び出そうとしました。 TableLayoutおよびTableRow(画面の前のレイアウト)で無効化とも呼ばれます。失敗。
GridViewが高さの拡張を拒否する理由は何ですか?
(GridView以外のビューグループを完全に使用できることに注意してください)
このコードを使用
public class MyGridView extends GridView {
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
私はこのようにしました:
このコードは、childのnumberに従ってGridView
の高さを設定します。
注:ここで5
は列の数です。
private void setDynamicHeight(GridView gridView) {
ListAdapter gridViewAdapter = gridView.getAdapter();
if (gridViewAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int items = gridViewAdapter.getCount();
int rows = 0;
View listItem = gridViewAdapter.getView(0, null, gridView);
listItem.measure(0, 0);
totalHeight = listItem.getMeasuredHeight();
float x = 1;
if( items > 5 ){
x = items/5;
rows = (int) (x + 1);
totalHeight *= rows;
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight;
gridView.setLayoutParams(params);
}
これがお役に立てば幸いです。
GridViewでonMeasure()が呼び出されたときに、heightModeがMeasureSpec.UNSPECIFIEDの場合、gridviewは含まれているすべての要素(およびいくつかのパディング)と同じ高さになります。
これを確実にするために、GridViewを拡張し、次のオーバーライドを含むクイックカスタムビューを作成できます。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.UNSPECIFIED);
}
これは私のために働いています:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/root"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@drawable/background" >
<!-- MORE LAYOUTS IF YOU WANT -->
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_weight="1"
Android:fillViewport="true" >
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content" >
<!-- MORE LAYOUTS IF YOU WANT -->
<GridView
Android:id="@+id/gridview"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
Android:layout_marginBottom="10dp"
Android:layout_marginLeft="20dp"
Android:layout_marginRight="20dp"
Android:layout_marginTop="5dp"
Android:gravity="center"
Android:horizontalSpacing="10dp"
Android:numColumns="auto_fit"
Android:stretchMode="columnWidth"
Android:verticalSpacing="10dp" >
</GridView>
<!-- MORE LAYOUTS IF YOU WANT -->
</RelativeLayout>
</ScrollView>
</RelativeLayout>
グラハムのソリューションは私にはうまくいきませんでした。ただし、これは(もう少しハッキングがあります)行いました: https://stackoverflow.com/a/8483078/479478
これは私のために働いています
public class MyGridView extends GridView {
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// set childs height to same value as child that has highest value
for(int i=0; i<getChildCount(); i++) {
MyLinearLayout child = (MyLinearLayout) getChildAt(i);
AbsListView.LayoutParams params = (AbsListView.LayoutParams) child.getLayoutParams();
params.height = MyLinearLayout.maxHeight;
child.setLayoutParams(params);
}
// calculate total height and apply to the grid
double numRow = Math.ceil((double) getCount() / (double) getNumColumns());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) this.getLayoutParams();
params.height = (int) numRow * MyLinearLayout.maxHeight;
this.setLayoutParams(params);
// invalidate after change grid's height
this.invalidate();
}
}
MyLinearLayoutクラス
public class MyLinearLayout extends LinearLayout {
public static int maxHeight = 0;
public MyLinearLayout(Context context) {
super(context);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (maxHeight<this.getMeasuredHeight()) maxHeight=this.getMeasuredHeight();
}
}
GridViewにはMyLinearLayoutのいくつかの子が含まれており、これがレイアウトです
<?xml version="1.0" encoding="utf-8"?>
<com.mysystem.view.MyLinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="100dp"
Android:layout_height="100dp"
Android:background="#ddd"
Android:padding="0.5dp"
Android:layout_gravity="top"
Android:gravity="center_horizontal"
Android:orientation="vertical">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="#fff"
Android:padding="20dp"
Android:orientation="vertical">
<ImageView
Android:id="@+id/img_menu"
Android:layout_width="30dp"
Android:layout_gravity="center_horizontal"
Android:layout_height="30dp"
Android:layout_marginTop="5dp"/>
<TextView
Android:id="@+id/tv_menu"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_marginTop="5dp"
Android:textAlignment="center"
Android:textColor="#000"
Android:text="Title"
Android:textSize="10sp"/>
</LinearLayout>
</com.mysystem.view.MyLinearLayout>