根据父级的类型生成 LayoutParams
我发现自己需要完全用 Java 创建一个 View,而不知道父级的具体类型是什么。
示例:
public View getView(int position, View convertView, ViewGroup parent){
if(null == convertView){
convertView = new TextView(parent.getContext());
}
((TextView) convertView).setText(getItem(position).getName());
}
现在假设我想更改此设置,以便 ConvertView 在两个方向上都是 wrap_content 。由于这是一个适配器,我想避免将适配器与父级的具体类型耦合,但是我在 setLayoutParams() 中给它的 LayoutParams 必须是正确的具体类型,否则应用程序将崩溃(即,如果父级是ListView 必须是 ListView.LayoutParams,如果是 LinearLayout,则必须是 LinearLayout.LayoutParams,等等)。我也不想使用 switch 语句,因为这只是一种更灵活的耦合形式,如果我将此适配器附加到视图,我没想到我仍然会崩溃。有没有通用的方法来做到这一点?
I find myself needing to create a View completely in Java without knowing what concrete type the parent is.
example:
public View getView(int position, View convertView, ViewGroup parent){
if(null == convertView){
convertView = new TextView(parent.getContext());
}
((TextView) convertView).setText(getItem(position).getName());
}
Now suppose I wanted to change this so that the convertView was wrap_content in both directions. Since this is an Adapter, I'd like to avoid coupling the Adapter with the concrete type of the parent, but the LayoutParams I give it in setLayoutParams() has to be the correct concrete type otherwise the app will crash (i.e. if parent is a ListView it has to be ListView.LayoutParams, if it's a LinearLayout it must be a LinearLayout.LayoutParams, etc.). I don't want to use a switch statement either since that's just a more flexible form of coupling, and if I attach this adapter to a view I didn't anticipate I still end up with a crash. Is there a generic way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您可以使用以下代码来完成此操作:
编辑:
上面的方法不起作用,因为
ViewGroup.generateLayoutParams()
需要在传递的中设置
。android:layout_width
和android:layout_height
>属性集如果您将ViewGroup.LayoutParams
与任何布局一起使用,那么一切都会正常工作。但是,如果您将LinearLayout.LayoutParams
与RelativeLayout
一起使用,则会引发异常。编辑:
对于这个问题有一个可行的解决方案,但我不太喜欢。解决方案是使用有效的
AttributeSet
调用generateLayoutParams()
。您可以使用至少两种不同的方法创建 AttributeSet 对象。我已经实现了其中一个:res\layout\params.xml:
SomeActivity.java:
创建
AttributeSet
对象的另一种方法是实现AttributeSet
接口并使其返回android:layout_width
、android:layout_height
以及其他你需要的布局属性。You can do this using the following code:
EDIT:
The method above doesn't work because
ViewGroup.generateLayoutParams()
requiresandroid:layout_width
andandroid:layout_height
to be set in the passedAttributeSet
.If you useViewGroup.LayoutParams
with any layout then everything will work fine. But if you useLinearLayout.LayoutParams
withRelativeLayout
for example, then an exception will be thrown.EDIT:
There's one working solution for this problem which I don't really like. The solution is to call
generateLayoutParams()
with validAttributeSet
. You can create anAttributeSet
object using at least two different approaches. One of them I've implemented:res\layout\params.xml:
SomeActivity.java:
Another way to create an
AttributeSet
object is to implementAttributeSet
interface and make it returnandroid:layout_width
,android:layout_height
and other layout attributes you need.我对此有以下解决方法:
您无法自己自动生成正确的
LayoutParams
,除非您做了一些 hacky 的事情,所以您应该创建一个为您自动生成它们的情况:只需将视图添加到容器中。之后,您可以从视图中获取它们并执行您需要的操作。唯一需要注意的是,如果您不需要自己将视图添加到容器中,则稍后必须从容器中删除视图,但这应该不是问题。
I have the following workaround for this:
You cannot autogenerate the correct
LayoutParams
yourself unless you do something hacky, so you should just create a situation where they will be autogenerated for you: just add the view to the container. After that you can get them from the view and do what you need.The only caveat is that if you don't need to add the view to the container yourself, you'll have to remove the view from it later, but this shouldn't be a problem.
所有
LayoutParams
类都有一个通用超类:ViewGroup.LayoutParams
。所有流行的布局(FrameLayout
、LinearLayout
、ConstraintLayout
等)都使用ViewGroup.MarginLayoutParams
作为它们各自的 LayoutParams 类。因此,如果您只需要宽度、高度和边距,则可以创建 ViewGroup.MarginLayoutParams 并将其作为布局参数传递给 ViewGroup 的任何子类。然后,容器将使用受保护的 LayoutParams ViewGroup#generateLayoutParams(ViewGroup.LayoutParams p) 自动将更通用的 ViewGroup.MarginLayoutParams 转换为自己的布局参数。
此代码适用于任何
container
类,包括LinearLayout
、RelativeLayout
等:All
LayoutParams
classes have one general superclass:ViewGroup.LayoutParams
. And all popular layouts (FrameLayout
,LinearLayout
,ConstraintLayout
, etc.) useViewGroup.MarginLayoutParams
as base class for their respectiveLayoutParams
classes.So if you just need width, height and margins, you can create
ViewGroup.MarginLayoutParams
and pass it as layout params to any subclass ofViewGroup
. What will happen then is container will automatically convert more genericViewGroup.MarginLayoutParams
into its own layout parameters usingprotected LayoutParams ViewGroup#generateLayoutParams(ViewGroup.LayoutParams p)
.This code will work for any
container
class, includingLinearLayout
,RelativeLayout
, etc:为什么没有人(还 -> 参见 2016.05)在这里提到一种基于反射的方法?
1.切入点:
2.用法:
why no one (yet -> see 2016.05) has mentioned here an approach based on reflections ?
1. entry point:
2. usages: