在android中以编程方式创建视图时如何传递AttributeSet

Posted

技术标签:

【中文标题】在android中以编程方式创建视图时如何传递AttributeSet【英文标题】:How to pass AttributeSet when creating view programmatically in android 【发布时间】:2015-05-15 16:41:05 【问题描述】:

然后我像水平视图一样以编程方式创建,如何以编程方式传递 AttributeSet。

我的构造函数如下所示:

public HorizontalListView(Context context, AttributeSet attrs) 
        super(context, attrs);
    

我试过这个:

mHlvSimpleList= new HorizontalListView(mcontext,R.style.niceview);

错误:

构造函数 Horizo​​ntalListView(Context, int) 未定义

在 style.xml 中

<style name="niceview">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>

</style>

horizo​​ntalistview构造函数匹配参数如何传递AttributeSet?

【问题讨论】:

***.com/a/25457076/1105214 我发现最简单的方法是简单地为自定义视图制作布局并对其进行膨胀,如果您有多个略有不同的实例,只需创建一个基本样式并使用 @987654325 对其进行子类化@, &lt;style="DeceptaDroid" parent="Droid"&gt; 【参考方案1】:

ContextAttributeSet 的构造函数用于当您的视图从 xml 膨胀时。您不应该使用它来创建对象。您应该使用带有Context 作为参数的构造函数。

AttributeSet是接口,你可以创建then的实例并实现所有方法,如下所示:

AttributeSet attrs = new AttributeSet()
        @Override
        public int getAttributeCount() 
            return 0;
        

        @Override
        public String getAttributeName(int index) 
            return null;
        

        @Override
        public String getAttributeValue(int index) 
            return null;
        

        @Override
        public String getAttributeValue(String namespace, String name) 
            return null;
        

        @Override
        public String getPositionDescription() 
            return null;
        

        @Override
        public int getAttributeNameResource(int index) 
            return 0;
        

        @Override
        public int getAttributeListValue(String namespace, String attribute, String[] options, int defaultValue) 
            return 0;
        

        @Override
        public boolean getAttributeBooleanValue(String namespace, String attribute, boolean defaultValue) 
            return false;
        

        @Override
        public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) 
            return 0;
        

        @Override
        public int getAttributeIntValue(String namespace, String attribute, int defaultValue) 
            return 0;
        

        @Override
        public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) 
            return 0;
        

        @Override
        public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) 
            return 0;
        

        @Override
        public int getAttributeListValue(int index, String[] options, int defaultValue) 
            return 0;
        

        @Override
        public boolean getAttributeBooleanValue(int index, boolean defaultValue) 
            return false;
        

        @Override
        public int getAttributeResourceValue(int index, int defaultValue) 
            return 0;
        

        @Override
        public int getAttributeIntValue(int index, int defaultValue) 
            return 0;
        

        @Override
        public int getAttributeUnsignedIntValue(int index, int defaultValue) 
            return 0;
        

        @Override
        public float getAttributeFloatValue(int index, float defaultValue) 
            return 0;
        

        @Override
        public String getIdAttribute() 
            return null;
        

        @Override
        public String getClassAttribute() 
            return null;
        

        @Override
        public int getIdAttributeResourceValue(int defaultValue) 
            return 0;
        

        @Override
        public int getStyleAttribute() 
            return 0;
        
    ; 

并使用它

TextView textView = new TextView(this, attrs);

但是这是不正确的方式

您应该使用视图中的方法来设置视图的属性。

例如设置 LayoutParams 有两种方法

首先通过方法setLayoutParams()

view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

将视图添加到 ViewGroup 的第二个;

viewGroup.addView(yourView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

当您拥有或想要将视图添加到例如 RelativeLayout 时,您应该使用与此 ViewGroup 相关的 LayoutParams。是RelativeLayout.LayoutParams

【讨论】:

我关心的是,如何在android的构造函数中传递AttributeSet。 您不应该这样做,当您在 xml 中创建视图时,创建者会使用具有两个参数的构造函数 如果你想手动创建你的对象,你必须使用以Context为参数的构造函数并通过方法设置你的属性。 但是在Horizo​​ntal Constructore 中是在上下文中接受两个参数一个,而另一个是AttributeSet,因此,如何在没有attrs 的情况下以编程方式创建Horizo​​ntalListView 视图,但它需要attrs 参数。 您自己实现的 AttributeSet 接口将不起作用。 Android 会抛出 java.lang.ClassCastException: cannot be cast to android.content.res.XmlBlock$Parser【参考方案2】:

我有办法从 xml 文件中获取 AttributeSet。

XmlPullParser parser = getResources().getXml(R.xml.test);
        try 
            parser.next();
            parser.nextTag();
         catch (Exception e) 
            e.printStackTrace();
        

        AttributeSet attr = Xml.asAttributeSet(parser);
        int count = attr.getAttributeCount();

如果计数值大于0,则表示你得到了一个正确的AttributeSet。

我的 xml/test.xml 是这样的:

<?xml version="1.0" encoding="utf-8"?>
<com.galoisli.myapplication.MyListView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:id="@+id/listView"
    android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true" />

【讨论】:

我对这个 android 开发还是很陌生。为什么这不是公认的答案?这似乎很有意义.... @HumbleWebDev B/c 确实不需要重新实现框架已经提供的功能 - MyListView 已经在布局文件中,因此它的膨胀将通过属性设置为它的“通货膨胀”构造函数(MyListView(Context c, AttributeSet a)。除了对框架进行一些黑客攻击之外,我真的想不出任何其他用途,但可能是错误的。 @HumbleWebDev 该框架将这种代码隐藏在私有方法中是有充分理由的——这样用户就可以从它的实现中抽象出来。一个应用程序的这些 sn-ps 越多,它的向后兼容性就越差,就越脆弱。 这应该是公认的答案! 在 Android 中,您可以在 XML 中设置属性,但类本身没有等效的 setter/getter。因此,如果您在代码中创建视图/首选项,那么您将陷入困境。一个示例是 Preference 中的 allowDividerBelow。【参考方案3】:

我在处理一个忘记实现SomeView(Context) 构造函数并且只有SomeView(Context, AttributeSet) 可用的视图时遇到了这个问题。不过,从 source code of ViewGroup 看来,SomeView(context) 将等同于 SomeView(context, null)

【讨论】:

【参考方案4】:

您可以创建引用自定义样式的属性。然后你应该能够使用

来实例化它
mHlvSimpleList= new HorizontalListView(mcontext, R.attr.niceview);

那里有一个完整的例子 https://gist.github.com/romannurik/7026222

【讨论】:

该要点显示正在使用的 3 个参数 View(Context, AttributeSet, int) 其中 R.attr.niceview 是指向默认样式的属性

以上是关于在android中以编程方式创建视图时如何传递AttributeSet的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中以编程方式创建多个列表

多个ListViews在android中以编程方式创建

在android中以编程方式将EditText视图约束到复选框?

如何在android中以编程方式查找TextView的文本区域(高度/宽度)

如何在 Android 上的 TabLayout 中以编程方式添加选项卡

如何在 Android 中以编程方式创建 TabLayout