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

发布于 2024-12-02 11:11:47 字数 3031 浏览 0 评论 0原文

我有一个扩展 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);
}

但是,当在 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)

第 204 行指的是 params 的实例化。

我注意到 GridView 和 LinearLayout 共享父 ViewGroup,因此我尝试使用 ViewGroup.LayoutParams。然而,这将导致 gridview 的相同行为(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);

或者不尝试回收当前的布局参数:

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 不喜欢它......

I have a custom class (touchbutton) extending the TextView class. I am having trouble resizing the button manually. I can get the button to work for only one type of layout or container, but not both. For the most part, Touchbutton is in gridviews so my method to change the size is as so:

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

However, when the TouchButton is resized in a LinearLayout (for example) I get a crash with the 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)

Line 204 refers to the instantiation of params.

I noticed that both GridView and LinearLayout share the parent ViewGroup, so i tried using ViewGroup.LayoutParams. This, however, this will lead to the same behavior for gridviews (logcat citing the same line).

Does anyone know how I might make this work for any type of layout or widget?

UPDATE:
As recommended i tried with View group again:

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

or without trying to recycle the current layoutparams:

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

And i get the same type of error:

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)

Update 2:
It seems that using the ViewGroup.LayoutParams specified above works for the LinearLayout. However, as seen above, the gridview doesn't like it...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一曲琵琶半遮面シ 2024-12-09 11:11:47

要了解这里发生的情况,您需要查看 Android 源代码。 ViewGroup generateLayoutParams 中有一个方法,JavaDoc 指出:

根据提供的布局返回一组安全的布局参数
参数。当 ViewGroup 传递一个布局参数不包含的 View 时
通过测试
checkLayoutParams(android .view.ViewGroup.LayoutParams),这个方法是
调用。此方法应返回一组新的合适的布局参数
对于此 ViewGroup,可能通过复制适当的属性
来自指定的布局参数集。

如果您查看 LinearLayout 和 AbsListView(GridView 的父级)源代码,您会发现它们将其子布局参数分别转换为 LinearLayout.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);
    }
}

To understand what happens here you need to look in the Android source. There is a method in ViewGroup generateLayoutParams which JavaDoc states:

Returns a safe set of layout parameters based on the supplied layout
params. When a ViewGroup is passed a View whose layout params do not
pass the test of
checkLayoutParams(android.view.ViewGroup.LayoutParams), this method is
invoked. This method should return a new set of layout params suitable
for this ViewGroup, possibly by copying the appropriate attributes
from the specified set of layout params.

If you look at LinearLayout and AbsListView (the parent of GridView) source you'll see they convert their children layout params to LinearsLayout.LayoutParams and AbsListView.LayoutParams respectively. But this conversion only happens when the child is added to the layout.
Thus if you add your TouchButton to the LinearLayout (programmaticaly or via XML) it will receive LinearsLayout.LayoutParams and, if you add it to the GridView (via an adapter) it receives AbsListView.LayoutParams.
But if you set layout params manually afterwards, you will get ClassCastException somewhere in the parent container code (since it expects its children layout params to be of some specific type).

For the solution of your issue I suggest you the following:

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);
    }
}
好听的两个字的网名 2024-12-09 11:11:47

为什么要强制转换 LayoutParams?

Button.getLayoutParams() 应返回 ViewGroup.LayoutParams,您可以访问其高度和宽度 - 无需强制转换。您确定在尝试 ViewGroup.LayoutParams 时没有执行以下操作:(

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

那仍然会失败)。

无论如何,请使用此方法:

ViewGroup.LayoutParams params = getLayoutParams();

然后,如果您仍然遇到异常,请发布该异常 - 而不是带有强制转换的异常。

Why are you casting LayoutParams at all?

Button.getLayoutParams() should return ViewGroup.LayoutParams, which you can access the height and width on - no cast needed. Are you sure when you tried ViewGroup.LayoutParams you didn't do something like:

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

(That'll still fail).

In any case, use this:

ViewGroup.LayoutParams params = getLayoutParams();

Then if you still get an exception, post that one - not the one with the casting.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文