如何将视图引用传递给android自定义视图?

ano*_*nim 21 android custom-view

我做了如下

1)创建一个风格

<declare-styleable name="Viewee">
    <attr name="linkedView" format="reference"/>
</declare-styleable>
Run Code Online (Sandbox Code Playgroud)

2)定义自定义视图布局

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#ffc0">
    <TextView
            android:id="@+id/custom_text"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="[text]"
            />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

3)创建所需的类

public class Viewee extends LinearLayout
{
public Viewee(Context context, AttributeSet attributeSet)
{
    super(context, attributeSet);
    View.inflate(context, R.layout.viewee, this);
    TextView textView = (TextView) findViewById(R.id.custom_text);
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee);
    int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0);
    if (id != 0)
    {
        View view = findViewById(id);
        textView.setText(((TextView) view).getText().toString());
    }

    typedArray.recycle();
}
}
Run Code Online (Sandbox Code Playgroud)

最后是在下面的活动中

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.ns"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
    <TextView
            android:id="@+id/tvTest"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="android"/>
    <com.ns.Viewee
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            app:linkedView="@+id/tvTest"
            />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

现在虽然我id在Viewee约束器中收到非零,但是findViewById(id)返回null并NullPointerException发生.

我错过了什么?

我这样做了

ano*_*nim 21

我找到了答案!

问题出findViewById(id)在我所说的地方.findViewById文档所述,只查找子视图而不是高层次级别的视图.因此,我必须调用类似的东西,getRootView().findViewById(id)但也会返回null因为我称之为不正确的地方.

Viewee约束器Viewee本身还没有连接到它的根,所以调用原因NullPointerException.

所以,如果我打电话给getRootView().findViewById(id)施工中的后别的地方,它工作正常,都"@+id/tvTest""@id/tvTest"正确.我测试过了!

答案如下

public class Viewee extends LinearLayout
{
    public Viewee(Context context, AttributeSet a)
    {
        super(context, attributeSet);
        View.inflate(context, R.layout.main6, this);
        TextView textView = (TextView) findViewById(R.id.custom_text);
        TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
        int id = t.getResourceId(R.styleable.Viewee_linkedView, 0);
        if (id != 0)
        {
            _id = id;
        }

        t.recycle();
    }

    private int _id;

    public void Foo()
    {
        TextView textView = (TextView) findViewById(R.id.custom_text);
        View view = getRootView().findViewById(_id);
        textView.setText(((TextView) view).getText().toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

并且Foo当需要通过其活动中的其他位置的引用ID处理附加视图时调用.

信用完全归功于在这篇文章中贡献的那些人.在提交问题之前我没有看过那个帖子.


Dar*_*ind 11

我知道这是一个老问题,但我想我会添加另一种方法,因为我想将所有内容封装到我的自定义视图中.

我不是从外面打电话,而是在层次结构中获得更高层次的另一种方式,onAttachedToWindow()而是我迷上了:

public class MyCustomView extends LinearLayout {
    private int siblingResourceId;
    private View siblingView;

    public MyCustomView(Context context, AttributeSet a) {
        super(context, attributeSet);
        inflate(context, R.layout.main6, this);
        TextView textView = (TextView) findViewById(R.id.custom_text);
        TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
        siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID);
        t.recycle();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (siblingResourceId != NO_ID) {
            siblingView = ((View) getParent()).findViewById(siblingResourceId);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

onAttachedToWindow被称为很早,但显然已经足够晚,整个视图层次结构已经解决.它至少可以完美地满足我的需求并且更加受控制,不需要从外部到工作的互动;-)

编辑: Kotlin代码添加

class MyCustomView(context: Context, attributeSet: AttributeSet) : LinearLayout(context, attributeSet) {
    private val siblingResourceId: Int
    private lateinit var siblingView: View

    // All other constructors left out for brevity.

    init {
        inflate(context, R.layout.main6, this)
        val textView = findViewById<TextView>(R.id.custom_text)
        val t = context.obtainStyledAttributes(a, R.styleable.Viewee)
        siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID)
        t.recycle()
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (siblingResourceId != NO_ID) {
            siblingView = (parent as View).findViewById(siblingResourceId) 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我们假设parent这个习惯ViewView自己的.