更改布局和容器的自定义按钮大小

Ian*_*Ian 4 android resize custom-view

我有一个自定义类(触摸按钮)扩展TextView类.我无法手动调整按钮大小.我可以让按钮只适用于一种类型的布局或容器,但不能同时使用两种.在大多数情况下,Touchbutton在gridviews中,所以我改变大小的方法如下:

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,当在LinearLayout中调整TouchButton的大小时(例如),我遇到了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)
Run Code Online (Sandbox Code Playgroud)

线204指的是参数的实例化.

我注意到两者GridViewLinearLayout分享了父母ViewGroup,所以我尝试使用ViewGroup.LayoutParams.但是,这将导致gridviews的相同行为(logcat引用同一行).

有谁知道我如何使这个工作适用于任何类型的布局或小部件?

更新:根据建议,我再次尝试使用View组:

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);
Run Code Online (Sandbox Code Playgroud)

或者不尝试回收当前的layoutparams:

setLayoutParams(new ViewGroup.LayoutParams(dim, dim));
Run Code Online (Sandbox Code Playgroud)

我得到了同样的错误:

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)
Run Code Online (Sandbox Code Playgroud)

更新2:似乎使用上面指定的ViewGroup.LayoutParams适用于LinearLayout.但是,如上所示,gridview不喜欢它......

Ido*_*lon 19

要了解此处发生的情况,您需要查看Android源代码.ViewGroup中有一个generateLayoutParamsJavaDoc声明的方法:

根据提供的布局参数返回一组安全的布局参数.当ViewGroup传递一个其布局参数未通过测试的视图时 checkLayoutParams(android.view.ViewGroup.LayoutParams),将调用此方法.此方法应返回适合此ViewGroup的一组新布局参数,可能是通过从指定的布局参数集复制适当的属性.

如果你看的LinearLayout和AbsListView源(GridView控件的父),你会看到他们转换自己的孩子布置PARAMS到LinearsLayout.LayoutParamsAbsListView.LayoutParams分别.但只有将子项添加到布局时才会发生此转换.
因此,如果您将TouchButton添加到LinearLayout(programmaticaly或通过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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 工作出色.谢谢你的决议和一个很好的解释. (2认同)