Изменить размер пользовательских кнопок для макетов и контейнеров - PullRequest
4 голосов
/ 02 сентября 2011

У меня есть собственный класс (сенсорная кнопка), расширяющий класс TextView.У меня проблемы с изменением размера кнопки вручную.Я могу заставить кнопку работать только для одного типа макета или контейнера, но не для обоих.В основном Touchbutton находится в виде сетки, поэтому мой метод для изменения размера таков:

private void setLayout(buttonsize_t size) {

    log("Setting Layout: "+buttonsize_t.getPxl(size));

    final float scale = getContext().getResources().getDisplayMetrics().density;
    int dim = (int) (buttonsize_t.getPxl(size) * scale + 0.5f);

    AbsListView.LayoutParams params = (AbsListView.LayoutParams) getLayoutParams();
    if (params != null) {
        params.height = dim;
        params.width = dim;
    }
    else {
        params = new AbsListView.LayoutParams(dim,dim);
    }
    setLayoutParams(params);
}

Однако, когда TouchButton изменяется в LinearLayout (например), я получаю сбой с Logcat:

09-01 19:18:35.630: ERROR/AndroidRuntime(20793): java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
09-01 19:18:35.630: ERROR/AndroidRuntime(20793):     at com.ians.aac3.TouchButton.setLayout(TouchButton.java:204)

Строка 204 относится к созданию параметров.

Я заметил, что и GridView, и LinearLayout имеют общий родительский элемент ViewGroup, поэтому я попытался использовать ViewGroup.LayoutParams,Это, однако, приведет к тому же поведению для gridviews (logcat со ссылкой на ту же строку).

Кто-нибудь знает, как я мог бы сделать эту работу для любого типа макета или виджета?

ОБНОВЛЕНИЕ: Как рекомендовано, я попытался снова с View group:

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.TextView;
.....
ViewGroup.LayoutParams params = getLayoutParams();
        if (params != null) {
            params.height = dim;
            params.width = dim;
        }
        else {
            params = new LayoutParams(dim,dim);
        }
        setLayoutParams(params);

или без попытки перезапустить текущий макетпараметры:

setLayoutParams(new ViewGroup.LayoutParams(dim, dim));

И я получаю такую ​​же ошибку:

09-02 09:10:49.680: ERROR/AndroidRuntime(7069): java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.widget.GridView.onMeasure(GridView.java:1028)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.view.View.measure(View.java:10828)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:267)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.view.View.measure(View.java:10828)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351)
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1284)

Обновление 2: кажется, что использование ViewGroup.LayoutParams, указанное выше, работает для LinearLayout.Однако, как видно выше, gridview не нравится ...

Ответы [ 2 ]

19 голосов
/ 09 сентября 2011

Чтобы понять, что здесь происходит, нужно заглянуть в источник Android.В ViewGroup generateLayoutParams существует метод, который JavaDoc утверждает:

Возвращает безопасный набор параметров макета на основе предоставленных параметров макета.Когда ViewGroup передается View, параметры макета которого не проходят тест checkLayoutParams(android.view.ViewGroup.LayoutParams), этот метод вызывается.Этот метод должен возвращать новый набор параметров макета, подходящий для этой ViewGroup, возможно, путем копирования соответствующих атрибутов из указанного набора параметров макета.

Если вы посмотрите на LinearLayout и AbsListView (родительский элемент GridView)) источник, который вы увидите, они преобразуют свои дочерние параметры макета в LinearsLayout.LayoutParams и AbsListView.LayoutParams соответственно.Но это преобразование происходит только тогда, когда дочерний элемент добавляется в макет.
Таким образом, если вы добавите TouchButton к LinearLayout (программно или через XML), он получит LinearsLayout.LayoutParams и, если вы добавите его в GridView (черезадаптера) он получает AbsListView.LayoutParams.
Но если впоследствии вы установите параметры макета вручную, вы получите ClassCastException где-нибудь в коде родительского контейнера (поскольку он ожидает, что его дочерние параметры макета будут иметь какой-то определенный тип).

Для решения вашей проблемы предлагаю вам следующее:

private void setLayout(buttonsize_t size) {

    log("Setting Layout: "+buttonsize_t.getPxl(size));

    final float scale = getContext().getResources().getDisplayMetrics().density;
    int dim = (int) (buttonsize_t.getPxl(size) * scale + 0.5f);

    ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams();
    if (params != null) {  
        params.height = dim;
        params.width = dim;
        setLayoutParams(params);
    } else {
      // the LayoutParams was not set yet, it must be the GridView 
      // which delays setting till child rendering
      params = new AbsListView.LayoutParams(dim, dim);
      setLayoutParams(params);
    }
}
0 голосов
/ 02 сентября 2011

Почему вы вообще используете LayoutParams?

Button.getLayoutParams() должен возвращать ViewGroup.LayoutParams, для которого вы можете получить доступ к высоте и ширине - нет необходимости в приведении. Вы уверены, что при попытке ViewGroup.LayoutParams вы не сделали что-то вроде:

ViewGroup.LayoutParams params = (AbsListView.LayoutParams) getLayoutParams();

(Это все равно не получится).

В любом случае используйте это:

ViewGroup.LayoutParams params = getLayoutParams();

Тогда, если вы все равно получите исключение, опубликуйте это, а не то, которое было на кастинге.

...