setContentView and findViewById

9

阅读了一些相关帖子后,我已经知道在尝试通过id查找元素之前必须显式调用setContentView来设置Activity-View-Hierarchy。我已经创建了一个具有充气视图的Activity,并且一切都运行良好。问题是当我尝试使用下一个xml和代码将另一个视图设置到此活动时:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:background="#B12A6D"
tools:context=".MainActivity"
android:orientation="vertical"
>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="top"
    android:background="@drawable/bg_purple_500"
    android:layout_margin="0dp"
    >

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/GridLayout1"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight="50"
        android:columnCount="4"
        android:rowCount="4"
        android:orientation="horizontal"
        tools:context=".GridXMLActivity"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        >

         <ImageView
            android:id="@+id/my_bnt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/icon_new_game"
            android:contentDescription="@string/text"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_marginBottom="10dp"
            />
</GridLayout>

</LinearLayout>

</RelativeLayout>

代码:

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

}


....

protected void method_triggered_from_UI_thread() {

  // Inflate other layout...
  View view = View.inflate(this, R.layout.my_layout, null) ;
  setContentView(view);
  ImageView btn = (ImageView) findViewById(R.id.my_bnt);
  // btn is null...

}

我尝试过其他微小的变化:


View mainView = findViewById(android.R.id.content);
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.my_layout, (ViewGroup) mainView, false)  ;
setContentView(view);
ImageView btn = (ImageView) view.findViewById(R.id.my_bnt);

我总是得到btn == null。我做错了什么吗?
谢谢

1
mainView 是什么? - ρяσѕρєя K
新的LinearLayout(mainActivity)而不是(ViewGroup)mainView不起作用。 - acimutal
是的,my_layout具有id my_btn。 - acimutal
我确定那是正确的ID。 - acimutal
发布 XML,这样我就可以清楚地看到问题所在。如果您分享 XML,我可以解决您的问题。 - Piyush
显示剩余12条评论
6个回答

2
你可以尝试使用LayoutInflater。
View inflatedView = LayoutoutInflater.from(context).inflate(R.layout, null);
setContentView(inflatedView);

愉快的编码


1
你需要等待替换完成。尝试这样做:
View view = View.inflate(this, R.layout.my_layout, null);
view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {          
     @Override          
     public void onGlobalLayout() {              
        // continue the initialization from here:
        btn = (ImageView) view.findViewById(R.id.my_bnt);
        //...

        view.getViewTreeObserver().removeGlobalOnLayoutListener(this);        
     }      
}); 
setContentView(view);

0

抱歉,我没有意识到我的id my_bnt存在于现有布局之一中(而不是在layout-land或layout-xlarge中)。

谢谢你的帮助


0
你确定btn和bnt是一样的吗?
我建议使用Fragments Google dev Fragments 不过,如果你想这样做,可以给main_activity.xml中的'outer' Layout指定一个特定的id,比如rootView。然后调用以下代码:
protected void methodTriggeredFromUiThread(){
    LinearLayout rootView = findViewById(R.id.rootView);
    View view = View.inflate(this, R.layout.my_layout, null) ;
    rootView.removeAllViews();
    rootView.addView(view);
    view.findViewById(R.id.my_bnt); 
}

要使用片段,请为您的活动可能具有的每种视图类型创建实现Fragment的类。您的main_activity仅将持有一个FrameLayout(除了持久标题,选项卡等)。由于按钮是位于片段内的视图,该片段位于调用findViewById(R.id.btn)的主活动中的任何位置都将产生按钮,只要加载了片段即可。

activity_main.xml中的某个地方:

 <FrameLayout
        android:id="@+id/fragmentHolder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
  </FrameLayout>

MainActivity.java

public class MainActivity extends Activity {
    private FragmentManager mFragmentManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadFragment(new DemoFragment());
    }
    protected void loadFragment(Fragment fragmentToLoad) {
        FragmentTransaction fragmentTransaction = mFragmentManager
            .beginTransaction();
        fragmentTransaction.replace(R.id.fragmentHolder, fragmentToLoad);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();
    }
}

DemoFragment.java

public class DemoFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.my_layout,
                container, false);
    }
}

我知道在活动中创建片段的标准方法,但在这种情况下,我正在尝试仅使用一个活动并动态更改GUI元素(通过交换布局)。 - acimutal

0
你可以尝试在你的R.layout.activity_main中添加一些ViewGroup(例如FrameLayout),然后在method_triggered_from_UI_thread()方法中将充气的视图添加到该容器中:
protected void method_triggered_from_UI_thread() {

// Inflate other layout...
  View view = View.inflate(this, R.layout.my_layout, null);

// add new view to the container view in activity layout
 (ViewGroup) findViewById(R.id.container).addView(view);

ImageView btn = (ImageView) findViewById(R.id.my_bnt);

}

-2
You can't assign a view,and do findviewbyid to an activity outside oncreate, an it just won't work. 
you need to rearrange your code in 
//declare image as global variable
ImageView btn;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
   Bundle extraArgs = getIntent().getExtras();
String layoutname=extraArgs.get("LayoutName");
if(layoutname="main")
    setContentView(R.layout.activity_main);
else 

  setContentView(R.layout.my_layout);
  btn = (ImageView) findViewById(R.id.my_bnt);

}



protected void method_triggered_from_UI_thread()
{
//Call the main activity again with bundle giving view 
Intent intent = new Intent();
intent.setClass(this, MainActivity.class);
intent.putExtra("LayoutName", "UR_LAYOUT_NAME");
startActivity(intent);/// or use startactivityforresult,

//access btn here
}

дҪ зҡ„еӣһзӯ”зҡ„第дёҖйғЁеҲҶжҳҜй”ҷиҜҜзҡ„пјҢдҪ еҸҜд»ҘеңЁдҪ зҡ„activityзұ»зҡ„д»»дҪ•ең°ж–№дҪҝз”ЁfindViewByIdж–№жі•пјҢдҪ д№ҹеҸҜд»ҘеңЁonCreatePartж–№жі•д№ӢеӨ–и°ғз”ЁsetContentViewгҖӮ - Gaëtan Maisse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接