私は(XMLを介して宣言的にではなく)プログラム的に次のことを達成しようとしています。
<RelativeLayout...>
<TextView ...
Android:id="@+id/label1" />
<TextView ...
Android:id="@+id/label2"
Android:layout_below: "@id/label1" />
</RelativeLayout>
言い換えれば、2番目のTextView
を最初のものの下に表示するにはどうすればよいですか。ただし、コードでそれを行いたいのです。
RelativeLayout layout = new RelativeLayout(this);
TextView label1 = new TextView(this);
TextView label2 = new TextView(this);
...
layout.addView(label1);
layout.addView(label2);
setContentView(layout);
ありがとう、TreeUK。私は一般的な方向性を理解していますが、それでもまだうまくいきません - "B"は "A"と重なっています。何がおかしいのですか?
RelativeLayout layout = new RelativeLayout(this);
TextView tv1 = new TextView(this);
tv1.setText("A");
TextView tv2 = new TextView(this);
tv2.setText("B");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.RIGHT_OF, tv1.getId());
layout.addView(tv1);
layout.addView(tv2, lp);
私が一緒にできたことから、LayoutParamsを使ってビューを追加しなければなりません。
LinearLayout linearLayout = new LinearLayout(this);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
parentView.addView(linearLayout, relativeParams);
プログラム的にアイテムを相対的に配置するためには、すべてのクレジットを保護する必要があります。それらにIDを割り当てる必要があります。
TextView tv1 = new TextView(this);
tv1.setId(1);
TextView tv2 = new TextView(this);
tv2.setId(2);
それでaddRule(RelativeLayout.RIGHT_OF, tv1.getId());
長い話を短くすると、相対レイアウトでは、要素をレイアウト内に配置します。
新しいRelativeLayout.LayoutParamsを作成します。
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(...)
(親の内容を埋めたり、コンテンツをラップしたりする必要がある場合は絶対数、XMLリソースを参照するなど)
規則を追加する:規則は、親、または階層内の他の「兄弟」を指します。
lp.addRule(RelativeLayout.BELOW, someOtherView.getId())
lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
レイアウトパラメータを適用するだけです。そのための最も「健康的な」方法は次のとおりです。
parentLayout.addView(myView, lp)
注意:レイアウトコールバックからレイアウトを変更しないでください。これはビューが実際のサイズになるときなので、そうするのは魅力的です。ただし、その場合は予期しない結果が予想されます。
この問題には4時間しかかかりませんでした。最後にあなたがビューIDとしてゼロを使用してはいけませんであることに気づきました。あなたはそれがNO_ID == -1として許可されていると思うでしょう、しかしあなたがあなたの見解にそれを与えるならば、物事は混乱を招く傾向があります...
Android 22最小実行可能例
ソース:
import Android.app.Activity;
import Android.os.Bundle;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.RelativeLayout;
import Android.widget.TextView;
public class Main extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1;
tv1 = new TextView(this);
tv1.setText("tv1");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
// tv2.
final TextView tv2;
tv2 = new TextView(this);
tv2.setText("tv2");
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.FILL_PARENT);
lp.addRule(RelativeLayout.BELOW, tv1.getId());
relativeLayout.addView(tv2, lp);
// tv3.
final TextView tv3;
tv3 = new TextView(this);
tv3.setText("tv3");
RelativeLayout.LayoutParams lp2 = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
lp2.addRule(RelativeLayout.BELOW, tv2.getId());
relativeLayout.addView(tv3, lp2);
this.setContentView(relativeLayout);
}
}
Android create project ...
によって生成されたデフォルトプロジェクトで動作します。 最小限のビルドコードでGitHubリポジトリ 。
コール
tv1.setId(1)
後に
tv1.setText("A");
試してください:
EditText edt = (EditText) findViewById(R.id.YourEditText);
RelativeLayout.LayoutParams lp =
new RelativeLayout.LayoutParams
(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT
);
lp.setMargins(25, 0, 0, 0); // move 25 px to right (increase left margin)
edt.setLayoutParams(lp); // lp.setMargins(left, top, right, bottom);
ViewGroup.MarginLayoutParamsを使用したこのアプローチは、私にとって役に立ちました。
RelativeLayout myLayout = (RelativeLayout) findViewById(R.id.my_layout);
TextView someTextView = ...
int leftMargin = Util.getXPos();
int topMargin = Util.getYPos();
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
lp.setMargins(leftMargin, topMargin, 0, 0);
myLayout.addView(someTextView, lp);
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
final RelativeLayout relativeLayout = new RelativeLayout(this);
final TextView tv1 = new TextView(this);
tv1.setText("tv1 is here");
// Setting an ID is mandatory.
tv1.setId(View.generateViewId());
relativeLayout.addView(tv1);
final TextView tv2 = new TextView(this);
tv2.setText("tv2 is here");
// We are defining layout params for tv2 which will be added to its parent relativelayout.
// The type of the LayoutParams depends on the parent type.
RelativeLayout.LayoutParams tv2LayoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
//Also, we want tv2 to appear below tv1, so we are adding rule to tv2LayoutParams.
tv2LayoutParams.addRule(RelativeLayout.BELOW, tv1.getId());
//Now, adding the child view tv2 to relativelayout, and setting tv2LayoutParams to be set on view tv2.
relativeLayout.addView(tv2);
tv2.setLayoutParams(tv2LayoutParams);
//Or we can combined the above two steps in one line of code
//relativeLayout.addView(tv2, tv2LayoutParams);
this.setContentView(relativeLayout);
}
}
あなたが本当に手動でレイアウトしたいのであれば、私は標準レイアウトをまったく使用しないことをお勧めします。あなた自身でそれをすべてしなさい、ここでkotlinの例:
class ProgrammaticalLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ViewGroup(context, attrs, defStyleAttr) {
private val firstTextView = TextView(context).apply {
test = "First Text"
}
private val secondTextView = TextView(context).apply {
text = "Second Text"
}
init {
addView(firstTextView)
addView(secondTextView)
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
// center the views verticaly and horizontaly
val firstTextLeft = (measuredWidth - firstTextView.measuredWidth) / 2
val firstTextTop = (measuredHeight - (firstTextView.measuredHeight + secondTextView.measuredHeight)) / 2
firstTextView.layout(firstTextLeft,firstTextTop, firstTextLeft + firstTextView.measuredWidth,firstTextTop + firstTextView.measuredHeight)
val secondTextLeft = (measuredWidth - secondTextView.measuredWidth) / 2
val secondTextTop = firstTextView.bottom
secondTextView.layout(secondTextLeft,secondTextTop, secondTextLeft + secondTextView.measuredWidth,secondTextTop + secondTextView.measuredHeight)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// just assume we`re getting measured exactly by the parent
val measuredWidth = MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = MeasureSpec.getSize(heightMeasureSpec)
firstTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
secondTextView.measures(MeasureSpec.makeMeasureSpec(meeasuredWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED))
setMeasuredDimension(measuredWidth, measuredHeight)
}
}
これにより、これがどのように機能するのかがわかります。