studio - relative layout xml android




In Android, come posso impostare i margini in dp a livello di codice? (8)

In this , this e this thread ho cercato di trovare una risposta su come impostare i margini su una singola vista. Tuttavia, mi chiedevo se non c'è un modo più semplice. Spiegherò perché preferirei non voler utilizzare questo approccio:

Ho un pulsante personalizzato che estende Button. Se lo sfondo è impostato su qualcosa di diverso dallo sfondo predefinito (chiamando setBackgroundResource(int id) o setBackgroundDrawable(Drawable d) ), voglio che i margini siano 0. Se lo chiamo:

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

Voglio che i margini vengano ripristinati a -3dp (ho già letto here come convertire da pixel a dp, quindi una volta che so come impostare i margini in px, posso gestire la conversione da solo). Ma poiché questo viene chiamato nella classe CustomButton , il genitore può variare da LinearLayout a TableLayout, e preferirei non fargli ottenere il suo genitore e controllare l'istanza di quel genitore. Anche questo sarà piuttosto insolito, immagino.

Inoltre, quando si chiama (usando LayoutParams) parentLayout.addView(myCustomButton, newParams) , non so se questo lo aggiunge alla posizione corretta (non l'ho comunque provato), diciamo il pulsante centrale di una riga di cinque.

Domanda: esiste un modo più semplice per impostare il margine di un singolo pulsante a livello di codice oltre a utilizzare LayoutParams?

EDIT: Conosco il modo LayoutParams, ma mi piacerebbe una soluzione che eviti di gestire ogni tipo di contenitore:

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

Perché this.getLayoutParams(); restituisce un ViewGroup.LayoutParams , che non ha gli attributi topMargin , bottomMargin , leftMargin , rightMargin . L'istanza di mc che vedi è solo un MarginContainer che contiene i margini di offset (-3dp) e (oml, omr, omt, omb) e i margini originali (ml, mr, mt, mb).


Ecco la risposta all-in-one con gli aggiornamenti recenti:

Passaggio 1, per aggiornare il margine

L'idea di base è ottenere il margine e aggiornarlo. L'aggiornamento verrà applicato automaticamente e non è necessario ripristinarlo. Per ottenere i parametri del layout, chiama semplicemente questo metodo:

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

Il LayoutParams deriva dal layout della tua vista. Se la vista proviene da un layout lineare, è necessario importare LinearLayout.LayoutParams . Se si utilizza il layout relativo, importare LinearLayout.LayoutParams , ecc.

Ora, se si imposta il margine utilizzando Layout_marginLeft , Right , ecc, è necessario aggiornare il margine in questo modo

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

Se si imposta il margine utilizzando il nuovo layout_marginStart , è necessario aggiornare il margine in questo modo

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

Passaggio 2, per aggiornare il margine in dp

Tutti e due i modi di aggiornare il margine sopra sono aggiornati in pixel. Devi eseguire una traduzione di dp in pixel.

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

Ora metti il ​​valore calcolato alle funzioni di aggiornamento del margine sopra e dovresti essere tutto pronto


È necessario utilizzare LayoutParams per impostare i margini dei pulsanti:

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

A seconda del layout utilizzato, è necessario utilizzare RelativeLayout.LayoutParams o LinearLayout.LayoutParams .

E per convertire la tua misura in pixel in pixel, prova questo:

Resources r = mContext.getResources();
int px = (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        yourdpmeasure, 
        r.getDisplayMetrics()
);

Il miglior modo di sempre:

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

Come chiamare il metodo:

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

Spero che questo ti possa aiutare.



Quando si è in una vista personalizzata, è possibile utilizzare getDimensionPixelSize(R.dimen.dimen_value) , nel mio caso, ho aggiunto il margine in LayoutParams creato sul metodo init .

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

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

Questo metodo ti consente di impostare il margine in 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);
}

AGGIORNARE

È possibile modificare il parametro più adatto alle proprie esigenze.


layout_margin è un vincolo che un bambino vista dice al genitore. Tuttavia è compito del genitore scegliere se consentire o meno margine. Fondamentalmente impostando android: layout_margin = "10dp", il bambino implorava il gruppo di visualizzazione genitore per allocare lo spazio che è 10dp più grande della sua dimensione effettiva. (padding = "10dp", d'altra parte, significa che la vista figlio renderà il proprio contenuto 10dp più piccolo ).

Di conseguenza, non tutti i ViewGroup rispettano il margine . L'esempio più noto sarebbe la listview, in cui i margini degli elementi vengono ignorati. Prima di chiamare setMargin() su un LayoutParam, dovresti sempre assicurarti che la vista corrente stia vivendo in un ViewGroup che supporta il margine (es. LinearLayouot o RelativeLayout) e lancia il risultato di getLayoutParams() nei LayoutParam specifici che desideri. ( ViewGroup.LayoutParams non ha nemmeno il metodo setMargins() !)

La funzione qui sotto dovrebbe fare il trucco. Tuttavia, assicurati di sostituire RelativeLayout con il tipo della vista genitore.

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

int sizeInDP = 16;

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

Poi

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

O

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




margin