Defina programaticamente a altura no LayoutParams como pixels independentes da densidade

123

Existe alguma maneira de definir a altura / largura de um LayoutParams como pixels independentes da densidade (dp)? Parece que a altura / largura, quando definida de forma programática, está em pixels e não em dp.

psychotik
fonte

Respostas:

271

Você precisa converter seu valor de mergulho em pixels:

int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, <HEIGHT>, getResources().getDisplayMetrics());

Para mim, isso faz o truque.

Mokus
fonte
10
Eu acho que getActivity (). GetResources (). GetDimension (resourceID) fazem as operações de conversão corretas.
StErMi
3
Funciona para mim, mas difere ... se eu definir a largura / altura de um ImageView usando o método acima vs. o xml. No XML, defino 85dp enquanto o método acima precisa de "75" para produzir o mesmo tamanho. Alguma idéia do porquê?
Dirk
1
@Dirk Provavelmente, há um problema de preenchimento / margem quando você o define de forma programática (geralmente você precisa especificar o preenchimento quando define o código). Não deve haver diferença alguma entre definir dp em XML ou em código.
Tiago
11
 public static int getDPI(int size, DisplayMetrics metrics){
     return (size * metrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;        
 }

Chame a função assim,

DisplayMetrics metrics;
metrics = new DisplayMetrics();         
getWindowManager().getDefaultDisplay().getMetrics(metrics);

int heigh = getDPI(height or width, metrics);
Hades
fonte
Isso é ... realmente errado. Você codificou para suportar apenas um número fixo de densidades. Se você deseja escalar pelo fator de escala de densidade, basta multiplicar por developer.android.com/reference/android/util/…, que também seria o mesmo que fazer (tamanho * metrics.densityDpi) / DisplayMetrics.DENSITY_DEFAULT.
11111 hackbod
1
Sim, sua nova resposta é razoável. Ou, como eu disse, basta multiplicar por metrics.density. É pra isso que isto serve.
hackbod
6

Como pode ser usado várias vezes:

public static int convDpToPx(Context context, float dp) {
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
}

Achei mais prático usar a taxa de conversão, pois geralmente mais de um valor deve ser convertido. Como a taxa de conversão não muda, economiza um pouco de tempo de processamento.

/**
 * Get conversion rate from dp into px.<br>
 * E.g. to convert 100dp: px = (int) (100 * convRate);
 * @param context e.g. activity
 * @return conversion rate
 */
public static float convRateDpToPx(Context context) {
    return context.getResources().getDisplayMetrics().densityDpi / 160f;
}
Gunnar Bernstein
fonte
5

Aqui está o meu trecho:

public class DpiUtils {

    public static int toPixels(int dp, DisplayMetrics metrics) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics);
    }

}

Onde DisplayMetrics metrics = getResources().getDisplayMetrics()

romano
fonte
0

A solução respondida não funcionou para mim, a altura da vista ainda estava baixa. Acabei com isso, que funciona bem:

protected int dp2px(int dp){
    final float scale = getResources().getDisplayMetrics().density;
    return (int) (dp * scale + 0.5f);
}

E se você quiser o contrário, pixels para dp ...

protected float px2dp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}
Sr. L
fonte