findViewById在自定义视图中返回null,其中包含子视图

时间:2014-09-25 12:37:54

标签: android null android-custom-view findviewbyid

我正在开发一个View,它显示了一堆消息,它们之间产生fadeIn,fadeOut和等待时间。它有一堆消息,当我需要显示其中的一些时,我添加了它。此视图没有特定的设计,因此用户可以按照自己的意愿进行自定义。

我已经写好了3个超级构造函数。

XML布局是下一个:

    [... Others views ...]

    <com.example.lectorrss.Views.StatusMessage
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/statusMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:background="#6894ed">

            <ProgressBar
                android:id="@+id/progressBar"
                android:layout_centerVertical="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <TextView
                android:id="@+id/message"
                android:layout_toRightOf="@id/progressBar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:text="Hola"
                android:textColor="#fff"></TextView>

            </RelativeLayout>

        </com.example.lectorrss.Views.StatusMessage>


[... Other views ...]

在这种情况下,我希望我的自定义视图显示内部的视图(进度条+ textview),然后应用我想要的行为。

我的CustomView的代码是:

public class StatusMessage extends ViewGroup{

    private List<String> messagesStack;
    private Worker worker;

    public StatusMessage(Context context) {
        super(context);
    }

    public StatusMessage(Context context, AttributeSet attrs){
        super(context, attrs);

    }

    public StatusMessage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
     }


    @Override
    protected void onAttachedToWindow() {

        super.onAttachedToWindow();

        TextView txtView = (TextView) this.findViewById(R.id.message);
        if(txtView == null){
            Log.d("BrowsePortal", "TextView null");
        }else{
            // HERE, THE CODE CAN FIND OK THE VIEW I WANT
            Log.d("BrowsePortal", "TextView not null");
        }

        worker = new Worker(this);
        worker.execute();

    }

    [Other logic code about view]

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

    }

}

但是由于我的视图需要在消息之间等待时间,并且使用动画,我需要创建一个AsyncTask:

public class Worker extends AsyncTask<Void,String,Void>{

    private StatusMessage view;

    public Worker(StatusMessage view) {
        this.view = view;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        [I supressed all logic code here]
        return null;
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        TextView txtView = (TextView) view.findViewById(R.id.message);
        if(txtView == null){
            // But here the code return null
            Log.d("BrowsePortal", "TextView null");
        }else{
            Log.d("BrowsePortal", "TextView not null");
        }
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        [I supressed all logic code here]
    }
}

我的问题是来自asynctask,在progressUpdate上,当我需要访问textview时,findviewbyid返回null。但是尝试从自定义视图类而不是asynctask访问相同的视图,它可以工作。为什么从视图类我可以访问textview而不是从asynctask访问?

此外,在post执行后,相同的代码返回null。

我的asynctask在她的构造函数中得到了很好的视图,所以从这里可以很好地从customview中运行。

1 个答案:

答案 0 :(得分:0)

问题在于这一行:

import android.R我改为import [app_package].R;

然后,当我把这一行:

TextView txtView = (TextView) view.findViewById(R.id.message);

...该方法无法找到textview,因为它使用的是android.R而不是package.R的资源ID。

最奇怪的是,在我这次做的活动中,有时我犯了同样的错误,但我可以快速解决,因为Eclipse告诉我,指定的资源没有找到资源线的下划线,但由于某种原因,在这种情况下没有通知我。也许R.id.message是为android.R保留的。