this 、 this 、 この スレッド私は単一のビューでマージンを設定する方法についての答えを見つけようとしました。しかし、もっと簡単な方法がないのではないかと思いました。なぜ私がこのアプローチを使いたくないのかを説明します。
Buttonを拡張するカスタムButtonがあります。背景がデフォルトの背景以外に設定されている場合(setBackgroundResource(int id)
またはsetBackgroundDrawable(Drawable d)
のいずれかを呼び出して)、余白を0にします。これを呼び出すと、次のようになります。
public void setBackgroundToDefault() {
backgroundIsDefault = true;
super.setBackgroundResource(Android.R.drawable.btn_default);
// Set margins somehow
}
余白を-3dpにリセットしたい(既に ここで ピクセルからdpに変換する方法を読んだので、pxで余白を設定する方法がわかったら、自分で変換を管理できます)。しかし、これはCustomButton
クラスで呼び出されるので、親はLinearLayoutからTableLayoutまでさまざまであり、私は彼に自分の親を取得させてその親のインスタンスをチェックさせたくはありません。それもまたかなり不調であると思います。
また、(LayoutParamsを使用して)parentLayout.addView(myCustomButton, newParams)
を呼び出すとき、これが正しい位置に追加されるかどうかわかりません(ただし試していません)。5行の真ん中のボタンを言ってください。
質問:LayoutParamsを使用する以外に、プログラムで単一のボタンのマージンを設定するより簡単な方法はありますか?
編集:私はLayoutParamsの方法を知っているが、私はそれぞれの異なるコンテナタイプを処理することを回避する解決策が欲しいのですが:
ViewGroup.LayoutParams p = this.getLayoutParams();
if (p instanceof LinearLayout.LayoutParams) {
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
else if (p instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
else if (p instanceof TableRow.LayoutParams) {
TableRow.LayoutParams lp = (TableRow.LayoutParams)p;
if (_default) lp.setMargins(mc.oml, mc.omt, mc.omr, mc.omb);
else lp.setMargins(mc.ml, mc.mt, mc.mr, mc.mb);
this.setLayoutParams(lp);
}
}
this.getLayoutParams();
は、topMargin
、bottomMargin
、leftMargin
、rightMargin
という属性を持たないViewGroup.LayoutParams
を返すためです。あなたが見るmcインスタンスは、オフセット(-3dp)のマージンと(oml、omr、omt、omb)とオリジナルのマージン(ml、mr、mt、mb)を含むMarginContainer
です。
ボタンの余白を設定するにはLayoutParams
を使用してください。
LayoutParams params = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);
使用しているレイアウトに応じて、RelativeLayout.LayoutParams
またはLinearLayout.LayoutParams
を使用する必要があります。
そして、あなたのdp指標をピクセルに変換するために、これを試してください:
Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
yourdpmeasure,
r.getDisplayMetrics()
);
LayoutParams - 動作しません! ! !
使用タイプが必要です:MarginLayoutParams
MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;
MarginLayoutParamsのコード例:
http://www.codota.com/Android/classes/Android.view.ViewGroup.MarginLayoutParams
史上最高の方法:
private void setMargins (View view, int left, int top, int right, int bottom) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
p.setMargins(left, top, right, bottom);
view.requestLayout();
}
}
メソッドを呼び出す方法:
setMargins(mImageView, 50, 50, 50, 50);
これがお役に立てば幸いです。
int sizeInDP = 16;
int marginInDp = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
.getDisplayMetrics());
それから
layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
または
LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
マージンを更新するためのステップ1
基本的な考え方は、マージンを出してから更新することです。アップデートは自動的に適用されますので、元に戻す必要はありません。レイアウトパラメータを取得するには、単にこのメソッドを呼び出します。
LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();
LayoutParams
はあなたのビューのレイアウトから来ています。ビューが線形レイアウトからのものである場合は、LinearLayout.LayoutParams
をインポートする必要があります。相対レイアウトを使用する場合は、LinearLayout.LayoutParams
などをインポートしてください。
Layout_marginLeft
やRight
などを使ってマージンを設定する場合は、このようにマージンを更新する必要があります。
layoutParams.setMargins(left, top, right, bottom);
新しいlayout_marginStart
を使用してマージンを設定した場合は、この方法でマージンを更新する必要があります。
layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);
ステップ2、dpのマージンを更新する
上記のマージンを更新する2つの方法はすべてピクセル単位で更新することです。あなたはdpをピクセルに変換する必要があります。
float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;
計算された値を上記のマージン更新関数に入力すると、すべて設定されます。
この方法で Margin を _ dp _ に設定できます。
public void setMargin(Context con,ViewGroup.LayoutParams params,int dp) {
final float scale = con.getResources().getDisplayMetrics().density;
// convert the DP into pixel
int pixel = (int)(dp * scale + 0.5f);
ViewGroup.MarginLayoutParams s =(ViewGroup.MarginLayoutParams)params;
s.setMargins(pixel,pixel,pixel,pixel);
yourView.setLayoutParams(params);
}
_アップデート_
必要に応じてパラメータを変更できます。
layout_marginは、ビューの子がその親に伝える制約です。ただし、マージンを許可するかどうかを選択するのは、親の役割です。基本的にAndroid:layout_margin = "10dp"を設定することで、子は親ビューグループに実際のサイズより 10dp大きい - スペースを割り当てるように訴えています。 (padding = "10dp"は、その一方で、子ビューが独自のコンテンツを 10 dp小さくする を意味します。)
その結果、 すべてのViewGroupがマージンを尊重するわけではありません 。最も悪名高い例はリストビューで、アイテムの余白は無視されます。 LayoutParamにsetMargin()
を呼び出す前に、現在のビューがマージンをサポートするViewGroup(LinearLayouotやRelativeLayoutなど)に属していることを必ず確認し、getLayoutParams()
の結果を必要な特定のLayoutParamsにキャストする必要があります。 (ViewGroup.LayoutParams
にはsetMargins()
メソッドさえありません!)
以下の関数がうまくいくはずです。 ただし、必ず親ビューのタイプにRelativeLayoutを代入してください。
private void setMargin(int marginInPx) {
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
setLayoutParams(lp);
}
あなたがカスタムビューにいるとき、あなたはgetDimensionPixelSize(R.dimen.dimen_value)
を使うことができます、私の場合、私はinit
メソッドで作成されたLayoutParamsにマージンを加えました。
コトリンで
init {
LayoutInflater.from(context).inflate(R.layout.my_layout, this, true)
layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
val margin = resources.getDimensionPixelSize(R.dimen.dimen_value)
setMargins(0, margin, 0, margin)
}
javaでは:
public class CustomView extends LinearLayout {
//..other constructors
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
int margin = getResources().getDimensionPixelSize(R.dimen.spacing_dime);
params.setMargins(0, margin, 0, margin);
setLayoutParams(params);
}
}
簡単な一行設定のために
((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);
しかし、これはif
ステートメントインスタンスがないので、LayoutParamsを誤って使用した場合は注意してください。
私の例では、ImageViewをLinearLayoutにプログラム的に追加しています。上部と下部の余白をImagerViewに設定しました。次に、ImageViewをLinearLayoutに追加します。
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmap);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(0, 20, 0, 40);
imageView.setLayoutParams(params);
linearLayout.addView(imageView);
それが便利であると思うかもしれないあなたのそれらのためのKotlin拡張機能を作成しました。
Dpではなくピクセルを渡すようにしてください。ハッピーコーディング:)
fun View.addLayoutMargins(left: Int? = null, top: Int? = null,
right: Int? = null, bottom: Int? = null) {
this.layoutParams = ViewGroup.MarginLayoutParams(this.layoutParams)
.apply {
left?.let { leftMargin = it }
top?.let { topMargin = it }
right?.let { rightMargin = it }
bottom?.let { bottomMargin = it }
}
}
この方法を使って、あなたのデバイスに合わせて変換される20のような静的二次元を置くことができます
public static int dpToPx(int dp)
{
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
今日のように、最善の方法はおそらくAirBnBが提供する Paris ライブラリを使うことです。
その後、スタイルは次のように適用できます。
Paris.style(myView).apply(R.style.MyStyle);
アノテーションを使用してカスタムビュー(ビューを拡張する場合)もサポートします。
@Styleable and @Style
更新しました:
ViewGroup.LayoutParams
を使ってレイアウトの幅と高さを設定した方法と同じです。
ViewGroup.MarginLayoutParams
を使って幅、高さ、マージンを設定することができます。
ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);
メソッドsetMargins();
はそれぞれleft、top、right、bottomの値を取ります。左から時計回りに!.
この方法を使用して、dpにマージンを設定します。
private void setMargins (View view, int left, int top, int right, int bottom) {
if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
final float scale = getBaseContext().getResources().getDisplayMetrics().density;
// convert the DP into pixel
int l = (int)(left * scale + 0.5f);
int r = (int)(right * scale + 0.5f);
int t = (int)(top * scale + 0.5f);
int b = (int)(bottom * scale + 0.5f);
p.setMargins(l, t, r, b);
view.requestLayout();
}
}
メソッドを呼び出す:
setMargins(linearLayout,5,0,5,0);
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
linearLayout.setBackgroundResource(R.drawable.smartlight_background);
それを継承し、そこに余白を設定して、アクティビティがFrameLayout
の元のレイアウトパラメータとは異なる背景と一緒に画面の一部にのみ表示されるように、私はsetContentView
に変換して余白を設定する必要がありました。
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.activity);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
linearLayout.setBackgroundColor(getResources().getColor(R.color.full_white));
setContentView(linearLayout,layoutParams);
他の誰も、同じ活動を使用したり、異なるメニューから活動を開いたことに基づいてマージンを変更するために働いていませんでした! setLayoutParamsは私のために働きませんでした - デバイスは毎回クラッシュするでしょう。これらはハードコードされた数字ですが - これはデモンストレーション目的のためのコードの例にすぎません。