如何从子级访问父级中的布局项?

时间:2012-03-18 21:57:54

标签: android android-layout

我有以下父xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_places_linearLayout" >

    <LinearLayout
        android:id="@+id/loadingPanel"
        style="@style/GenericProgressBackground" >

        <ProgressBar style="@style/GenericProgressIndicator" />
    </LinearLayout>

    <com.example.ListView
        android:id="@+id/bottomactionbar"
        style="@style/BottomActionBar" />

</LinearLayout>

com.example.ListView是我的自定义组件,包含AsyncTask。完成此任务后,我想将父级的ProgressBar可见性设置为GONE。

因此,当子组件中的AsyncTask完成时,我尝试以下操作:

LinearLayout llParent = (LinearLayout)getParent();

((LinearLayout)llParent.findViewById(R.id.loadingPanel)).setVisibility(View.GONE);

不幸的是,llParent.findViewById(R.id.loadingPanel)行是空的......我有什么机会可以克服这个问题?

谢谢, 菲利普

3 个答案:

答案 0 :(得分:3)

在我看来,当ListView的AsyncTask到达onPostExecute时,你想要的是一个自定义ListView可以调用的侦听器或委托方法。这会使您的自定义组件可重复使用(例如,如果您在具有不同ID的ProgressBar的其他视图上使用它,该怎么办?)

我会使用单个方法(例如com.example.ListView.AsyncTaskCompletionListener)创建一个内部接口(onAsyncTaskComplete或其他),给com.example.ListView一个该类型的实例变量,并拥有Activity实现了接口和方法。

在自定义ListView的AsyncTask的onPostExecute中,检查侦听器实例变量是否为null,然后在其上调用接口方法。

在Activity中设置ListView时,将ListView的侦听器实例变量设置为Activity(myListView.setAsyncTaskCompletionListener(this);)的实例,并在侦听器方法中,将ProgressBar可见性设置为GONE。

ListView片段:

package com.example;
public class ListView extends android.widget.ListView {
    private AsyncTaskCompletionListener listener;
    public AsyncTaskCompletionListener getAsyncTaskCompletionListener() {
        return listener;
    }
    public void setAsyncTaskCompletionListener(AsyncTaskCompletionListener atcl) {
        listener = atcl;
    }
    ...
    public interface AsyncTaskCompletionListener {
        public void onAsyncTaskComplete();
    }
    private MyAsyncTask extends AsyncTask<Void,Void,Void> {
        ...
        protected void onPostExecute(Void result) {
            if (listener != null) {
                listener.onAsyncTaskComplete();
            }
        }
    }
}

您的活动摘要:

public MyActivity extends android.app.Activity implements com.example.ListView.AsyncTaskCompletionListener {
    com.example.ListView customListView;
    ProgressBar progressBar;
    ...
    public void onCreate(Bundle savedInstanceState) { // Could be onResume or somewhere else
        ...
        progressBar = (ProgressBar)findViewById(R.id.progress_horizontal);
        customListView = (com.example.ListView)findViewById(R.id.bottomactionbar);
        customListView.setAsyncTaskCompletionListener(this);
    }
    ...
    public void onAsyncTaskComplete() {
        progressBar.setVisibility(View.GONE);
    }
}

答案 1 :(得分:1)

首先,听起来像你真正想要的是ListFragment。无论您选择哪种方式,只需在ListView中为ProgressBar提供一个setter,并在onCreate()中传递它。然后,您可以干净地直接访问ListView中的ProgressBar(但总是检查null)。

答案 2 :(得分:0)

尝试只为您的进度条提供自己的ID,并直接访问它而不尝试通过其父级。此外,内部LinearLayout“loadingPanel”是不必要的。只需将进度条弹出到外部列表即可。这是一个XML布局的片段,包括SDK示例中的进度条:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ProgressBar android:id="@+id/progress_horizontal"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="200dip"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="50"
    android:secondaryProgress="75" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/progressbar_1_default_progress" />
...

另外,请尝试仅使用小写字母,数字和“_”来命名资源ID。