【问题标题】:setContentView and findViewByIdsetContentView 和 findViewById
【发布时间】:2015-10-20 22:15:06
【问题描述】:

在阅读了一些相关帖子后,我已经知道在尝试通过 id 将元素查找到 Activity-View-Hierarchy 之前,我必须显式调用 setContenView。我创建了一个带有膨胀视图的 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。我做错了什么?

谢谢

【问题讨论】:

  • ImageView btn = (ImageView) view.findViewById(R.id.my_bnt); 第一种情况
  • my_layout 是否有 ID 为 my_bnt 的 thr 按钮?
  • mainView 是什么?
  • 尝试使用new LinearLayout(mainActivity)而不是(ViewGroup) mainView作为第二个参数
  • 你能发布你的全部java代码吗?

标签: android


【解决方案1】:

你可以试试 LayoutInflater。

View inflatedView = LayoutoutInflater.from(context).inflate(R.layout, null);
setContentView(inflatedView);

快乐的编码

【讨论】:

    【解决方案2】:

    你确定 btn 和 bnt 是一样的吗?

    我建议使用 Fragments Google dev Fragments

    但是,如果您想这样做,请在 main_activity.xml 中为您的“外部”布局指定一个特定的 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); 
    }
    

    要使用片段,请为您的活动可能具有的每种视图类型创建一个实现片段的类。您的 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 元素(通过交换布局)
    【解决方案3】:

    您必须等待更换结束。试试这个:

    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);
    

    【讨论】:

      【解决方案4】:

      你可以试试这个,在你的 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);
      
      }
      

      【讨论】:

        【解决方案5】:

        抱歉,我没有意识到 id my_bnt 存在,但仅存在于现有布局之一中(不在 layout-land 中,也不在 layout-xlarge 中)。 谢谢你的帮助

        【讨论】:

          【解决方案6】:
          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
          }
          

          【讨论】:

          • 你的答案第一部分是错误的,你可以在你的活动类中到处使用findViewById方法,你也可以在onCreatePart方法之外调用setContentView。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多