Как изменить размер пользовательского представления программно?

164

Я кодирую пользовательское представление, расширенное от RelativeLayout, и хочу программно изменить его размер. Как я могу это сделать?

Класс пользовательского представления выглядит примерно так:

public ActiveSlideView(Context context, AttributeSet attr){
        super(context, attr);
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(inflater != null){       
            inflater.inflate(R.layout.active_slide, this);
        }
herbertD
источник

Ответы:

253

Android выдает исключение, если вам не удается передать высоту или ширину вида. Вместо того, чтобы создавать новый объект LayoutParams, используйте исходный, чтобы сохранить все остальные установленные параметры. Обратите внимание, что тип LayoutParams, возвращаемый getLayoutParams, является типом родительского макета, а не вида, размер которого вы изменяете .

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
smisiewicz
источник
2
Как упоминает @HerbertD, я также получаю ошибку, если я не использую LinearLayout.LayoutParams, даже если это RelativeLayout, размер которого я изменяю.
Мартин Белчер - AtWrk
6
@Eigo Согласно документации Android, LayoutParams передаются родительскому представлению, поскольку именно это представление отвечает за макет.
sstn
1
Должно ли значение in быть преобразовано в значение dp, или оно будет работать.
Дори
Это также предпочтительнее, так как позволяет избежать ненужного создания нового объекта LayoutParams
Стивен Кидсон
129
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));

Задача решена!

ПРИМЕЧАНИЕ. Обязательно используйте родительский макет LayoutParams. Мой есть LinearLayout.LayoutParams!

herbertD
источник
3
Wut. Почему бы вам не использоватьRelativeLayout.LayoutParams?
ЯМР
1
Это не сработало для меня, я получил исключение для класса.
Тапан Такер
4
@Tapan Thanker Используйте LayoutParams родительского макета. И мой родительский макет является LinearLayout.
ГербертD
10
Я написал более общую версию этого: private void resizeView(View view, int newWidth, int newHeight) { try { Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); view.setLayoutParams(ctor.newInstance(newWidth, newHeight)); } catch (Exception e) { e.printStackTrace(); } }
atroutt
2
Это сбросит все остальные параметры к значениям по умолчанию. @smisiewicz ответ лучше.
Фран Марзоа
66

Это работает для меня:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
Sileria
источник
7
Это намного лучше, чем другие ответы, потому что этот код не требует точного определения типа родительской ViewGroup.
Барт Бург
1
Вы знаете, в чем разница между вызовом requestLayout () и вызовом setLayoutParams (params)?
voghDev
2
setLayoutParams (params) включает requestLayout ().
illusionJJ
44

Допустим, вы хотели изменить размер представления в пикселях, не зависящих от устройства ( dp ): -

Вам нужно использовать метод с именем applyDimension, который является членом класса TypedValueдля преобразования из пикселей в dps. Так что, если я хочу установить высоту 150dp (скажем) - тогда я мог бы сделать это:

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) someLayout.getLayoutParams();
params.height = (int) pixels;
someLayout.setLayoutParams(params);

где выражение: getResources().getDisplayMetrics()получает плотность экрана / разрешение

Danield
источник
6
Вместо жесткого кодирования вашего измерения вы также можете использовать это для высоты в пикселях:float pixels = context.getResources().getDimensionPixelSize(R.dimen.card_height);
Франсуа Дерму
этот ответ более уместен как правильный ответ! Спасибо
Юнус Кулиев
6

попробуйте это:

...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
zed_0xff
источник
Извините, я не опубликовал весь вопрос, так как вы отвечаете на него. Теперь это весь вопрос. Спасибо!
herbertD
6

Вот более общая версия решения выше @herbertD:

private void resizeView(View view, int newWidth, int newHeight) { 
    try { 
        Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class); 
        view.setLayoutParams(ctor.newInstance(newWidth, newHeight));   
    } catch (Exception e) { 
        e.printStackTrace(); 
    }
}
atroutt
источник
@atroutt, ты буквально спас мой день :)
Касим
5

Я использовал этот способ, чтобы увеличить ширину пользовательского вида

customDrawingView.post(new Runnable() {
                            @Override
                            public void run() {
                                View view_instance = customDrawingView;
                                android.view.ViewGroup.LayoutParams params = view_instance
                                        .getLayoutParams();
                                int newLayoutWidth = customDrawingView
                                        .getWidth()
                                        + customDrawingView.getWidth();
                                params.width = newLayoutWidth;
                                view_instance.setLayoutParams(params);
                                screenWidthBackup = params.width;
                            }
                        });
AkhilGite
источник
4

Я решил это таким образом .. У меня есть в основном простой вид внутри XML-файла.

 View viewname = findViewById(R.id.prod_extra);
             prodExtra.getLayoutParams().height=64;
Приложения DazzleGifts
источник
2
ха-ха, очень наивный, но хорошо работающий способ, однако я рекомендую в конце концов вызвать setLayoutParams () для правильного распространения изменений на возможные вложенные дочерние элементы, поэтому после обновления .width и .height вызовите view.setLayoutParams (view.getLayoutParams ()), это также всегда
проверяйте
@Bhargav Рао, не могли бы вы помочь мне в этой теме: https://stackoverflow.com/q/44259342/6596724
tux-world
2

Если у вас есть только two or three condition(sizes)тогда, вы можете использовать @Overide, onMeasure как

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

И изменить свой размер для этих условий в классе CustomView легко.

Хар-э-ахмер хан
источник
1

если вы переопределяете onMeasure, не забудьте обновить новые размеры

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(newWidth, newHeight);
}
XurajB
источник
1

Вот как я этого добился. В Sileria answer он / она сделал следующее:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();

Это правильно, но мы ожидаем, что мы будем указывать высоту pixels, но я хотел указать, что dpя хочу, чтобы высота была, поэтому я добавил:

public int convertDpToPixelInt(float dp, Context context) {
    return (int) (dp * (((float) context.getResources().getDisplayMetrics().densityDpi) / 160.0f));
}

Так это будет выглядеть так:

ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
ClassA
источник
0

Вот что я сделал:

View myView;  
myView.getLayoutParams().height = 32;  
myView.getLayoutParams().width = 32;

Если существует группа представлений, к которой принадлежит это представление, вам также может потребоваться вызвать yourViewGroup.requestLayout (), чтобы оно вступило в силу.

us_david
источник