Di Android, bagaimana cara mengatur margin dalam dp secara terprogram?

401

Dalam hal ini , ini dan utas ini saya mencoba menemukan jawaban tentang cara mengatur margin pada satu tampilan. Namun, saya bertanya-tanya apakah tidak ada cara yang lebih mudah. Saya akan menjelaskan mengapa saya lebih suka tidak ingin menggunakan pendekatan ini:

Saya memiliki Tombol khusus yang meluas Tombol. Jika latar belakang diatur ke sesuatu selain latar belakang default (dengan memanggil salah satu setBackgroundResource(int id)atau setBackgroundDrawable(Drawable d)), saya ingin margin menjadi 0. Jika saya memanggil ini:

public void setBackgroundToDefault() {
    backgroundIsDefault = true;
    super.setBackgroundResource(android.R.drawable.btn_default);
    // Set margins somehow
}

Saya ingin margin diatur ulang ke -3dp (saya sudah membaca di sini cara mengkonversi dari piksel ke dp, jadi setelah saya tahu cara mengatur margin dalam px, saya dapat mengatur sendiri konversi). Tetapi karena ini disebut dalam CustomButtonkelas, induk dapat bervariasi dari LinearLayout ke TableLayout, dan saya lebih suka dia tidak meminta orang tuanya dan memeriksa contoh dari orang tua itu. Saya kira itu juga akan sangat buruk.

Juga, ketika memanggil (menggunakan LayoutParams) parentLayout.addView(myCustomButton, newParams), saya tidak tahu apakah ini menambahkannya ke posisi yang benar (belum mencoba), katakanlah tombol tengah dari lima baris.

Pertanyaan: Apakah ada cara yang lebih mudah untuk mengatur margin dari satu Tombol secara terprogram selain menggunakan LayoutParams?

EDIT: Saya tahu cara LayoutParams, tapi saya ingin solusi yang menghindari penanganan setiap jenis wadah yang berbeda:

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);
    }
}

Karena this.getLayoutParams();hasil sebuah ViewGroup.LayoutParams, yang tidak memiliki atribut topMargin, bottomMargin, leftMargin, rightMargin. Contoh mc yang Anda lihat hanyalah MarginContaineryang mengandung margin offset (-3dp) dan (oml, omr, omt, omb) dan margin asli (ml, mr, mt, mb).

stealthjong
sumber

Jawaban:

797

Anda harus menggunakan LayoutParamsuntuk mengatur margin tombol Anda:

LayoutParams params = new LayoutParams(
        LayoutParams.WRAP_CONTENT,      
        LayoutParams.WRAP_CONTENT
);
params.setMargins(left, top, right, bottom);
yourbutton.setLayoutParams(params);

Bergantung pada tata letak apa yang Anda gunakan, Anda harus menggunakan RelativeLayout.LayoutParamsatau LinearLayout.LayoutParams.

Dan untuk mengubah ukuran dp Anda menjadi piksel, coba ini:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);
throrin19
sumber
152
Dari paket mana saya harus mengimpor LayoutParams itu?
stealthjong
7
setMargins menggunakan px dan Anda akan menggunakan dp, konversi saya benar: dp -> px untuk menetapkan nilai margin yang benar.
throrin19
6
@ChristiaandeJong
16
itu tergantung dari tata letak Anda saat ini. Jika Anda berada di LinearLayout, gunakan LinearLayout.LayoutParams. RelativeLayout.LayoutParams sebaliknya
throrin19
5
Anda harus mengimpor layoutParams yang merupakan tata letak induk Anda. <linearlayout><relativelayout> <gridlayout> dan Anda bekerja dengan tata letak kisi. lalu, Anda perlu menggunakan relativelayout.layoutparams
Sruit A.Suk
228

LayoutParams - BUKAN BEKERJA! ! !

Perlu menggunakan jenis: MarginLayoutParams

MarginLayoutParams params = (MarginLayoutParams) vector8.getLayoutParams();
params.width = 200; params.leftMargin = 100; params.topMargin = 200;

Contoh Kode untuk MarginLayoutParams:

http://www.codota.com/android/classes/android.view.ViewGroup.MarginLayoutParams

Lyusten Elder
sumber
19
Benar, tetapi tidak perlu mengaturnya kembali, params yang diubah secara otomatis tercermin. Dengan demikian Anda dapat menghapus baris: vector8.setLayoutParams (params);
Wirsing
LayaoutParams biasanya membuat kebingungan saat mengatur margin ... Jadi, MarginLayoutParams ini sangat berguna. Terima kasih
Atul Bhardwaj
4
Anda DO perlu mengaturLayoutParams (params) setelah perubahan marging
Leo Droidcoder
saya menemukan MarginLayoutParams sebagai kelas baru hari ini #Terima kasih.
Tushar Pandey
Tidak berfungsi untuk Buttontampilan: ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button.getLayoutParams()pengembaliannull
Konstantin Konopko
118

Cara terbaik yang pernah ada:

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();
    }
}

Cara memanggil metode:

setMargins(mImageView, 50, 50, 50, 50);

Semoga ini bisa membantu Anda.

Hiren Patel
sumber
1
saya menghadapi masalah ketika saya mengatur setMargins (holder.vCenter, 0, 20, 0,0); seperti ini margin cuti di kedua sisi (atas dan bawah) ada apa dengan param di atas?
Arbaz.in
1
Jawaban sempurna yang luar biasa !! Terima kasih!!
Sjd
33
int sizeInDP = 16;

int marginInDp = (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, sizeInDP, getResources()
                    .getDisplayMetrics());

Kemudian

layoutParams = myView.getLayoutParams()
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);

Atau

LayoutParams layoutParams = new LayoutParams...
layoutParams.setMargins(marginInDp, marginInDp, marginInDp, marginInDp);
myView.setLayoutParams(layoutParams);
sagit
sumber
15

Inilah jawaban lengkap dengan pembaruan terkini:

Langkah 1, untuk memperbarui margin

Ide dasarnya adalah untuk mendapatkan margin dan memperbaruinya. Pembaruan akan diterapkan secara otomatis dan Anda tidak perlu mengaturnya kembali. Untuk mendapatkan parameter tata letak, cukup panggil metode ini:

LayoutParams layoutParams = (LayoutParams) yourView.findViewById(R.id.THE_ID).getLayoutParams();

Itu LayoutParamsberasal dari tata letak tampilan Anda. Jika tampilan dari tata letak linier, Anda perlu mengimpor LinearLayout.LayoutParams. Jika Anda menggunakan tata letak relatif, impor LinearLayout.LayoutParams, dll.

Sekarang, jika Anda menetapkan margin menggunakan Layout_marginLeft, Right, dll, Anda perlu memperbarui marjin dengan cara ini

layoutParams.setMargins(left, top, right, bottom);

Jika Anda menetapkan margin menggunakan yang baru layout_marginStart, Anda perlu memperbarui margin dengan cara ini

layoutParams.setMarginStart(start);
layoutParams.setMarginEnd(end);

Langkah 2, untuk memperbarui margin dalam dp

Kedua cara memperbarui margin di atas memperbarui dalam piksel. Anda perlu melakukan terjemahan dp ke piksel.

float dpRatio = context.getResources().getDisplayMetrics().density;
int pixelForDp = (int)dpValue * dpRatio;

Sekarang masukkan nilai yang dihitung ke fungsi pembaruan margin di atas dan Anda harus siap

Fangming
sumber
9

layout_margin adalah kendala yang anak view katakan kepada orang tuanya. Namun itu adalah peran orang tua untuk memilih apakah akan memberikan margin atau tidak. Pada dasarnya dengan mengatur android: layout_margin = "10dp", anak tersebut meminta grup tampilan induk untuk mengalokasikan ruang yang 10dp lebih besar dari ukuran sebenarnya. (padding = "10dp", di sisi lain, berarti tampilan anak akan membuat kontennya sendiri 10dp lebih kecil .)

Akibatnya, tidak semua ViewGroup menghargai margin . Contoh yang paling terkenal adalah listview, di mana margin item diabaikan. Sebelum Anda menelepon setMargin()ke LayoutParam, Anda harus selalu memastikan bahwa tampilan saat ini tinggal di ViewGroup yang mendukung margin (misalnya LinearLayouot atau RelativeLayout), dan melemparkan hasilnya getLayoutParams()ke LayoutParams spesifik yang Anda inginkan. ( ViewGroup.LayoutParamsbahkan tidak punyasetMargins() metode!)

Fungsi di bawah ini seharusnya melakukan trik. Namun pastikan Anda mengganti RelativeLayout dengan tipe tampilan induk.

private void setMargin(int marginInPx) {
    RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
    lp.setMargins(marginInPx,marginInPx, marginInPx, marginInPx);
    setLayoutParams(lp);
}
Ian Wong
sumber
9

Metode ini akan memungkinkan Anda mengatur Margin di 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);
}

MEMPERBARUI

Anda dapat mengubah parameter yang sesuai dengan kebutuhan Anda.

neferpitou
sumber
8

Di Kotlin akan terlihat seperti ini:

val layoutParams = (yourView?.layoutParams as? MarginLayoutParams)
layoutParams?.setMargins(40, 40, 40, 40)
yourView?.layoutParams = layoutParams
Morozov
sumber
3

Ketika Anda berada di Tampilan kustom, Anda dapat menggunakan getDimensionPixelSize(R.dimen.dimen_value), dalam kasus saya, saya menambahkan margin di LayoutParams dibuatinit metode.

Di Kotlin

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)
}

di Jawa:

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);
    }
}
aldajo92
sumber
1

Gunakan metode ini untuk mengatur margin dalam 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();
    }
}

panggil metode:

setMargins(linearLayout,5,0,5,0);
Ridwan Bin Sarwar
sumber
1

Untuk penggunaan pengaturan satu baris yang cepat

((LayoutParams) cvHolder.getLayoutParams()).setMargins(0, 0, 0, 0);

tetapi berhati-hatilah untuk segala penggunaan yang salah pada LayoutParams, karena ini tidak memiliki ifchech instance statment

Dasser Basyouni
sumber
1

Membuat fungsi Ekstensi Kotlin untuk Anda yang mungkin merasa nyaman.

Pastikan untuk memasukkan piksel, bukan dp. Selamat coding :)

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 }
            }
}
David Kim
sumber
1

Dalam contoh saya, saya menambahkan ImageView ke LinearLayout secara terprogram. Saya telah menetapkan margin atas dan bawah ke ImagerView. Kemudian menambahkan ImageView ke 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);
Rajeev Shetty
sumber
1

Anda dapat menggunakan metode ini dan meletakkan dimen statis seperti 20 yang dikonversi sesuai perangkat Anda

 public static int dpToPx(int dp) 
      {
          float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
  }
Piring Kawatra
sumber
0

Seperti hari ini, yang terbaik mungkin menggunakan Paris , perpustakaan yang disediakan oleh AirBnB.

Gaya kemudian dapat diterapkan seperti ini:

Paris.style(myView).apply(R.style.MyStyle);

itu juga mendukung tampilan khusus (jika Anda memperluas tampilan) menggunakan anotasi:

@Styleable and @Style
sonique
sumber
0

Anda harus menelepon

setPadding(int left, int top, int right, int bottom)

seperti itu: your_view.setPadding(0,16,0,0)

Apa yang Anda coba gunakan hanyalah pengambil.

Android studio menunjukkan apa yang padding...()sebenarnya berarti di java:

padding example Gambar hanya menunjukkan panggilangetPadding...()

Jika Anda ingin menambahkan margin ke TextView Anda, Anda harus LayoutParams:

val params =  LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT)
params.setMargins(int left, int top, int right, int bottom)
your_view.layoutParams = params
Saadat Sayem
sumber
-1
((FrameLayout.LayoutParams) linearLayout.getLayoutParams()).setMargins(450, 20, 0, 250);
        linearLayout.setBackgroundResource(R.drawable.smartlight_background);

Saya harus melemparkan tambang ke FrameLayoutuntuk LinearLayout karena mewarisi darinya dan mengatur margin di sana sehingga aktivitas hanya muncul di bagian layar bersama dengan latar belakang yang berbeda dari tata letak tata letak asli di 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);

Tidak ada yang bekerja untuk menggunakan aktivitas yang sama dan mengubah margin berdasarkan pada pembukaan aktivitas dari menu yang berbeda! setLayoutParams tidak pernah bekerja untuk saya - perangkat akan macet setiap saat. Meskipun ini adalah angka yang dikodekan dengan keras - ini hanya contoh kode untuk tujuan demonstrasi saja.

ali mcnamara
sumber
-1

Anda dapat menggunakan ViewGroup.MarginLayoutParamsuntuk mengatur lebar, tinggi dan margin

ViewGroup.MarginLayoutParams marginLayoutParams = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
marginLayoutParams.setMargins(0,16,0,16);
linearLayout.setLayoutParams(marginLayoutParams);

Di mana metode setMargins();mengambil nilai untuk masing-masing kiri, atas, kanan, bawah. Searah jarum jam !, mulai dari kiri.

mmmcho
sumber