我有一个扩展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);
}
然而,当在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
。但是,这将导致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);
或者没有尝试回收当前的layoutparams:
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不喜欢它......
答案 0 :(得分:19)
要了解这里发生了什么,您需要查看Android源代码。 ViewGroup generateLayoutParams
中有一个JavaDoc声明的方法:
根据提供的布局返回一组安全的布局参数 PARAMS。当ViewGroup传递一个其布局参数不具有的视图时 通过测试
checkLayoutParams(android.view.ViewGroup.LayoutParams)
,这种方法是 调用。此方法应返回一组适合的新布局参数 对于此ViewGroup,可能通过复制适当的属性 来自指定的布局参数集。
如果您查看LinearLayout和AbsListView(GridView的父级)源代码,您会看到他们将子级布局参数分别转换为LinearsLayout.LayoutParams
和AbsListView.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);
}
}
答案 1 :(得分:0)
为什么要投射LayoutParams?
Button.getLayoutParams()
应返回ViewGroup.LayoutParams
,您可以访问高度和宽度 - 无需投射。你确定当你尝试ViewGroup.LayoutParams
时没做过类似的事情吗?
ViewGroup.LayoutParams params = (AbsListView.LayoutParams) getLayoutParams();
(那仍然会失败)。
无论如何,请使用:
ViewGroup.LayoutParams params = getLayoutParams();
然后,如果你仍然得到一个例外,发布那个例外 - 而不是那个带有投射的那个。