TableLayout, TableRow and TextView
で構成されるビューがあります。グリッドのように見せたい。このグリッドの高さと幅を取得する必要があります。メソッドgetHeight()
およびgetWidth()
は常に0を返します。これは、グリッドを動的にフォーマットするとき、およびXMLバージョンを使用するときに発生します。
ビューのディメンションを取得する方法は?
以下は、デバッグで結果を確認するために使用したテストプログラムです。
import Android.app.Activity;
import Android.os.Bundle;
import Android.widget.TableLayout;
import Android.widget.TextView;
public class appwig extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
int vh = 0;
int vw = 0;
//Test-1 used the xml layout (which is displayed on the screen):
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight(); //<- getHeight returned 0, Why?
vw = tl.getWidth(); //<- getWidth returned 0, Why?
//Test-2 used a simple dynamically generated view:
TextView tv = new TextView(this);
tv.setHeight(20);
tv.setWidth(20);
vh = tv.getHeight(); //<- getHeight returned 0, Why?
vw = tv.getWidth(); //<- getWidth returned 0, Why?
} //eof method
} //eof class
OPはもうなくなったと思いますが、この答えが将来の検索者を助けることができるなら、私が見つけた解決策を投稿すると思いました。このコードをonCreate()
メソッドに追加しました:
編集: 07/05/11コメントからのコードを含める:
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable)tv.getBackground();
ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
ViewTreeObserver obs = tv.getViewTreeObserver();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
obs.removeOnGlobalLayoutListener(this);
} else {
obs.removeGlobalOnLayoutListener(this);
}
}
});
最初に、TextView
への最後の参照を取得します(onGlobalLayout()
メソッドでアクセスするため)。次に、ViewTreeObserver
からTextView
を取得し、OnGlobalLayoutListener
を追加して、onGLobalLayout
をオーバーライドし(ここで呼び出すスーパークラスメソッドではないようです...)、このリスナーにビューの測定値を知る必要があるコードを追加します。すべてが期待どおりに機能するため、これが役立つことを願っています。
代替ソリューションを追加して、アクティビティのonWindowFocusChangedメソッドをオーバーライドすると、そこからgetHeight()、getWidth()の値を取得できるようになります。
@Override
public void onWindowFocusChanged (boolean hasFocus) {
// the height will be set at this point
int height = myEverySoTallView.getMeasuredHeight();
}
まだ描画されていない要素の幅と高さを取得しようとしています。
デバッグを使用して、ある時点で停止すると、デバイスの画面がまだ空であることがわかります。これは、要素がまだ描画されていないためです。存在します。
そして、私は間違っているかもしれませんが、setWidth()
は常に尊重されず、Layout
はその子をレイアウトし、それらを測定する方法を決定します(child.measure()
を呼び出します)。したがって、setWidth()
を設定した場合、要素が描画された後にこの幅を取得することは保証されません。
必要なのは、ビューが実際に描画された後のどこかでgetMeasuredWidth()
(ビューの最新のメジャー)を使用することです。
最適なタイミングを見つけるために、Activity
ライフサイクルを調べてください。
http://developer.Android.com/reference/Android/app/Activity.html#ActivityLifecycle
次のようにOnGlobalLayoutListener
を使用することをお勧めします。
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (!mMeasured) {
// Here your view is already layed out and measured for the first time
mMeasured = true; // Some optional flag to mark, that we already got the sizes
}
}
});
このコードをonCreate()
に直接配置することができ、ビューがレイアウトされるときに呼び出されます。
このようなビューの投稿メソッドを使用します
post(new Runnable() {
@Override
public void run() {
Log.d(TAG, "width " + MyView.this.getMeasuredWidth());
}
});
onGlobalLayout()
を使用してTextView
のカスタム書式設定を試みましたが、@ George Baileyが気づいたように、onGlobalLayout()
は実際に2回呼び出されます。最初のレイアウトパスで1回、テキストの変更後2回です。
View.onSizeChanged()
は、テキストを変更した場合、メソッドが(レイアウトパス中に)1回だけ呼び出されるため、私にとってはうまく機能します。これにはTextView
のサブクラス化が必要でしたが、APIレベル11以降では View. addOnLayoutChangeListener()
を使用してサブクラス化を回避できます。
もう1つ、View.onSizeChanged()
でビューの正しい幅を取得するには、layout_width
をmatch_parent
ではなく、wrap_content
に設定する必要があります。
実際の画像を取得する前に、コンストラクタでサイズを取得しようとしていますか、または他のメソッドを実行しようとしていますか?
すべてのコンポーネントが実際に測定される前に寸法を取得することはありません(xmlは表示サイズ、親の位置などを知らないため)
OnSizeChanged()の後に値を取得してみてください(ゼロで呼び出すこともできます)、または実際の画像が取得されるのを待つだけです。
私はこれを見る必要があると思います:ビューのonSizeChanged()
を使用します。 onSizeChanged()
を使用してレイアウトまたはビューの高さと幅を動的に取得する方法に関する拡張コードスニペットがあります http://syedrakibalhasan.blogspot.com/2011/02/how-to-get-width-and-height -dimensions.html
F.Xとして。前述のように、OnLayoutChangeListener
を使用して、それ自体を追跡するビューに使用できます
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
// Make changes
}
});
初期レイアウトのみが必要な場合は、コールバックからリスナーを削除できます。
ViewTreeObserver
とonWindowFocusChanged()
はまったく必要ありません。
TextView
をレイアウトとして膨らませたり、その中にコンテンツを入れてLayoutParams
を設定したりすると、getMeasuredHeight()
とgetMeasuredWidth()
を使用できます。
BUTあなたはLinearLayouts
に注意してください(他のViewGroups
である可能性もあります)。問題は、onWindowFocusChanged()
の後に幅と高さを取得できることですが、ビューを追加しようとすると、すべてが描画されるまでその情報を取得できません。複数のTextViews
をLinearLayouts
に追加して、FlowLayout
(ラッピングスタイル)を模倣しようとしたため、Listeners
を使用できませんでした。プロセスが開始されると、同期して続行する必要があります。そのような場合、レイアウトにビューを追加するときに必要になるため、後で使用するために変数の幅を保持したい場合があります。
提案されたソリューションは機能しますが、ViewTreeObserver.OnGlobalLayoutListener
のドキュメントに基づいているため、すべての場合に最適なソリューションとは限りません
ビューツリー内のビューのグローバルレイアウト状態または可視性が変更されたときに呼び出されるコールバックのインターフェイス定義。
つまり、何度も呼び出され、常にビューが測定されるわけではありません(ビューの高さと幅が決定されます)
別の方法は、ViewTreeObserver.OnPreDrawListener
を使用することです。これは、ビューを描画する準備ができて、すべての測定値がある場合にのみ呼び出されます。
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnPreDrawListener(new OnPreDrawListener() {
@Override
public void onPreDraw() {
tv.getViewTreeObserver().removeOnPreDrawListener(this);
// Your view will have valid height and width at this point
tv.getHeight();
tv.getWidth();
}
});
高さと幅は、リクエストしているときまでにビューが作成されていないためゼロです。最も簡単な解決策は
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
view.getWidth(); //width is ready
}
});
この方法は、短くて鮮明なので、他の方法と比べて優れています。
Viewのライフサイクルを確認する必要があります。 http://developer.Android.com/reference/Android/view/View.html 通常、アクティビティがonResumeになるまで、幅と高さを確実に知る必要はありません。状態。
OnResume()で呼び出されるブロードキャストを使用できます
例えば:
int vh = 0;
int vw = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.maindemo); //<- includes the grid called "board"
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
TableLayout tl = (TableLayout) findViewById(R.id.board);
tl = (TableLayout) findViewById(R.id.board);
vh = tl.getHeight();
vw = tl.getWidth();
}
}, new IntentFilter("Test"));
}
protected void onResume() {
super.onResume();
Intent it = new Intent("Test");
sendBroadcast(it);
}
Kcoppockが応答した理由で、OnCreate()、onStart()、またはonResume()でもビューの高さを取得できません。