【问题标题】:Android Set Text of TextView in Fragment that is in FragmentPagerAdapterAndroid 在 FragmentPagerAdapter 中的 Fragment 中设置 TextView 的文本
【发布时间】:2014-07-03 16:37:17
【问题描述】:

这个让我发疯。基本上,我想创建一个ViewPager 并添加一些Fragments。然后,我想做的就是在FragmentTextViews 之一中设置一个值。我可以很好地添加Fragments,它们会附加,但是当我在第一个TextViews 中转到findViewById() 时,它会抛出NullPointerException。我一辈子都想不通为什么。

这是我目前的代码,如果需要更多,请告诉我。

public class SheetActivity extends FragmentActivity {

    // /////////////////////////////////////////////////////////////////////////
    // Variable Declaration
    // /////////////////////////////////////////////////////////////////////////
    private ViewPager               viewPager;
    private PagerTitleStrip         titleStrip;
    private String                  type;
    private FragmentPagerAdapter    fragmentPager;  //UPDATE

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sheet);

        viewPager = (ViewPager) findViewById(R.id.viewPager);
        titleStrip = (PagerTitleStrip) findViewById(R.id.viewPagerTitleStrip);

        // Determine which type of sheet to create
        Intent intent = getIntent();
        this.type = intent.getStringExtra("type");
        FragmentManager manager = getSupportFragmentManager();
        switch (type) {
            case "1":
                viewPager.setAdapter(new InstallAdapter(manager));
                break;
            case "2":
                viewPager.setAdapter(new InstallAdapter(manager));
                break;
        }
        fragmentPager = (FragmentPagerAdapter) viewPager.getAdapter();  //UPDATE
    }

    @Override
    public void onResume() {
        super.onResume();

        fragmentPager.getItem(0).setText("something"); //UPDATE
    }

    class MyAdapter extends FragmentPagerAdapter {

        private final String[]      TITLES      = { "Title1", "Title2" };
        private final int           PAGE_COUNT  = TITLES.length;
        private ArrayList<Fragment> FRAGMENTS   = null;

        public MyAdapter(FragmentManager fm) {
            super(fm);
            FRAGMENTS = new ArrayList<Fragment>();
            FRAGMENTS.add(new FragmentA());
            FRAGMENTS.add(new FragmentB());
        }

        @Override
        public Fragment getItem(int pos) {
            return FRAGMENTS.get(pos);
        }

        @Override
        public int getCount() {
            return PAGE_COUNT;
        }

        @Override
        public CharSequence getPageTitle(int pos) {
            return TITLES[pos];
        }
    }
}

我创建的所有Fragments 只覆盖了onCreateView() 方法,因此我可以显示正确的XML 布局。除此之外,它们是“库存”。为什么我无法与任何Fragments 中的元素进行交互?

更新:

那么做这样的事情?

public class FragmentA extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle inState) {
        return inflater.inflate(R.layout.fragment_a, container, false);
    }

    public void setText(String text) {
        TextView t = (TextView) getView().findViewById(R.id.someTextView);  //UPDATE
        t.setText(text);
    }
}

片段 A 的 XML 布局

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

    <TextView
        android:id="@+id/someTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:textSize="22sp" />

</LinearLayout>

【问题讨论】:

    标签: android android-fragments android-viewpager android-fragmentactivity


    【解决方案1】:

    TextView 位于片段布局中,而不是在导致 NPE 的 ViewPagersPagerAdapter 中。现在,您有 2 个选择。

    • 第一个是最简单的,您应该简单地将用于更改文本的代码移动到相应片段的类中,在本例中为 FragmentA。
    • 其次,您可以将TextView 设为FragmentA 静态,以便其他类可以访问它。所以你的代码看起来像这样:

       ....
       TextView myText;
      
       @Override
       public View onCreateView(....) {
      
           myLayout = ....;
      
           myText = myLayout.findViewById(yourID);
      
           ....
      }
      

    然后你会从其他地方更改文本(如果真的有必要的话):

       FragmentA.myText.setText("new text");
    

    说明方法二

    在您的片段中使用以下内容。

    public static void setText(String text) {
        TextView t = (TextView) getView().findViewById(R.id.someTextView);
        t.setText(text);
    }
    

    然后将文本更改为:

    FragmentA.setText("Lulz");
    

    【讨论】:

    • 之前,我尝试过类似getActivity().findViewById(R.id.someTextViewInFragmentA); 的方法,并将其实例化为TextView。但是当我尝试在上面设置文本时,我收到了另一个 NPE。
    • 在 onCreateView(..) 中,您应该使用分配给正在膨胀的布局的变量,并从中获取 ID,如上所示。无论如何,要使第二种方法起作用,片段必须已经启动,否则您将收到另一个 NPE。
    • 更新了我上面的问题。类似的东西?这也给了我一个 NPE。
    • 哦,我忘了说,在片段中获取对视图的引用,您使用 getView() 而不是 getActivity()。将 getActivity() 更改为 getView() 即可解决您的问题。
    • 你在哪里调用 setText(..) ?
    【解决方案2】:

    除非您打算在运行时更改值,否则您可以将值作为参数传递到片段中。我使用 Bundle 并将其作为 args 传递给 Fragment,然后从它的 args 中检索它。 More info here。如果你实现了这个,你的新片段的实例化可能看起来像这样:

    public InstallAdapter(FragmentManager fm) {
                super(fm);
                FRAGMENTS = new ArrayList<Fragment>();
                FRAGMENTS.add(FragmentA.newInstance("<text to set to the TextView>"));
                FRAGMENTS.add(FragmentB.newInstance("<text to set to the TextView>"));
            }
    

    但是,如果您计划在运行时更新该值(它会随着用户运行应用程序而改变),那么您希望使用接口来引导片段和活动之间的通信。 Info here。这可能是这样的:

    //Declare your values for activity;
        ISetTextInFragment setText;
        ISetTextInFragment setText2;
    ...
    //Add interface
    public interface ISetTextInFragment{
        public abstract void showText(String testToShow);
    }
    ...
    //your new InstallAdapter
    public InstallAdapter(FragmentManager fm) {
            super(fm);
    
            FRAGMENTS = new ArrayList<Fragment>();
    
            Fragment fragA = new FragmentA();
            setText= (ISetTextInFragment)fragA;
            FRAGMENTS.add(fragA);
    
            Fragment fragB = new FragmentB();
            setText2= (ISetTextInFragment)fragB;
            FRAGMENTS.add(fragB);
    }
    
    //then, you can do this from your activity:
    ...
    setText.showText("text to show");
    ...
    

    它会更新片段中的文本视图。

    虽然可以“更轻松地”完成,但推荐使用这些方法,因为它们减少了出现错误的机会,并使代码更具可读性和可维护性。

    编辑:这就是你的 Fragment 的样子(修改你的代码):

    public class FragmentA extends Fragment implements ISetTextInFragment {
    
        TextView myTextView;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle inState) {
            View v = inflater.inflate(R.layout.fragment_a, container, false);
            myTextView = (TextView)v.findViewbyId(R.id.someTextView)
            return v;
        }
    
        @Override
        public void showText(String text) {
            myTextView.setText(text);
        }
    }
    

    如果之后您仍然收到空指针异常,则您的 TextView 不在我需要的位置,即在 R.layout.fragment_a 文件中,它需要位于那里。 当然,除非您在片段完成加载之前调用接口方法。

    【讨论】:

    • 我将在两者中做后者。我以前使用Communicator 接口让Fragments 说话,但他们会让我findViewById 获取Fragments 中的元素——这不会出于某种原因。
    • 您希望在创建文本视图时(在您的 onCreateView() 中)将其实例化,然后在界面覆盖方法中进行设置。
    • 如果你在片段中调用 getView().findViewById(),它会找到你的 TextView。如果您在您的 ACVIVITY 中执行此操作,它不会找到它。
    • 在片段中调用 getView().findViewById() 时的另一个 NPE。
    • 您的 TextView 位于您在片段 onCreateView 中膨胀的 .xlm 文件中,对吗?你能发布你的代码吗?
    【解决方案3】:

    这一行:

    TextView t = (TextView) findViewById(R.id.someTextViewInFragmentA);
    

    正在您的 ParentActivity 中寻找视图。当然它不会找到它,那是你获得 NPE 的时候。

    试试这样的:

    1. 添加片段时为片段添加“标签”

    2. 使用someFragment = getSupportFragmentManager().findFragmentByTag("your_fragment_tag")

    3. 获取片段的视图 fragmentView = someFragment.getView();

    4. 最后找到你的TextView 并设置文字

      TextView t = (TextView) fragmentView.findViewById(R.id.someTextViewInFragmentA); t.setText("some text");

    【讨论】:

    • 这是我通常会做的,但是片段是由MyAdapter添加的,所以我没有标记它们。
    • 可以发MyAdapter的代码吗?我认为有一种方法可以在其中添加标签
    • @Aashir 也有道理。你不能从你的Fragment 类中更新TextView 吗?这不是更容易吗?
    • 更新了我上面的问题。类似的东西?这也给了我一个 NPE。
    • 关闭。您缺少两件事:1.您仍在尝试在 ParentActivity 中找到 TextView,这就是您仍然拥有 NPE 的原因。更改此TextView t = (TextView) getView().findViewById(R.id.someTextView); 2. 将方法更改为:public static void setText(String text) 然后您可以从 MainActivity 中的 onResume 方法访问它,如下所示: FragmentA.setText("your text");
    【解决方案4】:

    这行怎么改

    TextView t = (TextView) getView().findViewById(R.id.someTextView);  //UPDATE
    

    TextView t = (TextView) getActivity().findViewById(R.id.someTextView);  //UPDATE
    

    然后您可以尝试在“SheetActivity”中使用 .setText("some_string") 更新“t”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多