【问题标题】:Update a TextView in a ViewPager from another Fragment从另一个 Fragment 更新 ViewPager 中的 TextView
【发布时间】:2012-02-05 18:29:38
【问题描述】:

我正在尝试通过单击另一个 Fragment 上的按钮来更新 Fragment 中的 TextView。

实际上我实现了 Activity 的回调函数并且它确实有效,因为 Logcat 报告 TextView 中的文本已更改。问题是第一个片段中显示的 Textview 没有更新为新值!这就像 Fragment 需要更新什么的......

这是 ActionBarTabsPager 活动代码:

import java.util.ArrayList;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentManager.OnBackStackChangedListener;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActionBar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ActionBar.Tab;
import android.support.v4.app.SupportActivity;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.TextView;

/**
 * Demonstrates combining the action bar with a ViewPager to implement a tab UI
 * that switches between tabs and also allows the user to perform horizontal
 * flicks to move between the tabs.
 */
public class ActionBarTabsPager extends FragmentActivity implements SecondFragment.OnButtonClickedXListener{
    ViewPager  mViewPager;
    TabsAdapter mTabsAdapter;
    FragmentManager fm;



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

        setContentView(R.layout.actionbar_tabs_pager);



        if (savedInstanceState == null) {
             Fragment newFragment = new FirstFragment();
             FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
             ft.add(R.id.abs__custom, newFragment, "FirstFragment").commit();

             Fragment newFragment2 = new FirstFragment();
             FragmentTransaction ft2 = getSupportFragmentManager().beginTransaction();
             ft2.add(R.id.abs__custom, newFragment2, "SecondFragment").commit();
        }
        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        ActionBar.Tab tab1 = getSupportActionBar().newTab().setText("Fragment 1");
        ActionBar.Tab tab2 = getSupportActionBar().newTab().setText("Fragment 2");
        //ActionBar.Tab tab3 = getSupportActionBar().newTab().setText("Fragment 1");
        //ActionBar.Tab tab4 = getSupportActionBar().newTab().setText("Fragment 2");

        mViewPager = (ViewPager)findViewById(R.id.pager);
        mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);

            mTabsAdapter.addTab(tab1, FirstFragment.class);
            mTabsAdapter.addTab(tab2, SecondFragment.class);//LoaderCursorSupport.CursorLoaderListFragment.class);
            //mTabsAdapter.addTab(tab3, FirstFragment.class);//LoaderCustomSupport.AppListFragment.class);
            //mTabsAdapter.addTab(tab4, SecondFragment.class);//LoaderThrottleSupport.ThrottledLoaderListFragment.class);


        if (savedInstanceState != null) {
            getSupportActionBar().setSelectedNavigationItem(savedInstanceState.getInt("index"));
        }



    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("index", getSupportActionBar().getSelectedNavigationIndex());
    }

    /**
     * This is a helper class that implements the management of tabs and all
     * details of connecting a ViewPager with associated TabHost.  It relies on a
     * trick.  Normally a tab host has a simple API for supplying a View or
     * Intent that each tab will show.  This is not sufficient for switching
     * between pages.  So instead we make the content part of the tab host
     * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
     * view to show as the tab content.  It listens to changes in tabs, and takes
     * care of switch to the correct paged in the ViewPager whenever the selected
     * tab changes.
     */
    public class TabsAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
        private final Context mContext;
        private final ActionBar mActionBar;
        private final ViewPager mViewPager;
        private final ArrayList<String> mTabs = new ArrayList<String>();

        public TabsAdapter(FragmentActivity activity, ActionBar actionBar, ViewPager pager) {
            super(activity.getSupportFragmentManager());
            mContext = activity;
            mActionBar = actionBar;
            mViewPager = pager;
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);
        }

        public void addTab(ActionBar.Tab tab, Class<?> clss) {
            mTabs.add(clss.getName());
            mActionBar.addTab(tab.setTabListener(this));
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return mTabs.size();
        }

        @Override
        public Fragment getItem(int position) {
            return Fragment.instantiate(mContext, mTabs.get(position), null);
        }


        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            mActionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            mViewPager.setCurrentItem(tab.getPosition());

        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        }
    }

    @Override
    public void OnButtonClickedX(View v) {

        if (v==findViewById(R.id.button1)){
            Log.i("TRIGGERED","TRIGGERED");

            FirstFragment ff = (FirstFragment) getSupportFragmentManager().findFragmentByTag("FirstFragment");

            View root = ff.getView();
            TextView tv = (TextView) root.findViewById(R.id.textView1);
            Log.i("Text before Edit",""+tv.getText());
            tv.setText("MODIFIED");
            Log.i("Text after Edit",""+tv.getText());




        }
        // TODO Auto-generated method stub

    }





}

第一个片段:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FirstFragment extends Fragment {
    int mNum;


    /**
     * Create a new instance of FirstFragment, providing "num"
     * as an argument.
     */
    static FirstFragment newInstance(int num) {

        FirstFragment f = new FirstFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mNum = getArguments() != null ? getArguments().getInt("num") : 1;
    }

    /**
     * The Fragment's UI is just a simple text view showing its
     * instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.myfrag1, container, false);
        return v;
    }




}

SecondFragment:

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.SupportActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;

public  class SecondFragment extends Fragment {
    int mNum;
    OnButtonClickedXListener mListener;

    /**
     * Create a new instance of CountingFragment, providing "num"
     * as an argument.
     */
    static SecondFragment newInstance(int num) {
        SecondFragment f = new SecondFragment();

        // Supply num input as an argument.
        Bundle args = new Bundle();
        args.putInt("num", num);
        f.setArguments(args);

        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mNum = getArguments() != null ? getArguments().getInt("num") : 1;
    }

    /**
     * The Fragment's UI is just a simple text view showing its
     * instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.myfrag2, container, false);
        View button1 = v.findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mListener.OnButtonClickedX(v);
                // TODO Auto-generated method stub

            }
        });



        return v;
    }

    public interface OnButtonClickedXListener{
        public void OnButtonClickedX(View v);
    }

    @Override
    public void onAttach(SupportActivity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        try {
            mListener = (OnButtonClickedXListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnButtonClickedXListener");
        }
    }

}

myfrag1.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >



    <TextView
        android:id="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:text="No String"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

myfrag2.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >


    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="Button" />

</LinearLayout>

编辑:

即使将 ft.add() 中的 ContainerViewId 更改为 0,也不会影响最终渲染。所以我猜渲染是由

mTabsAdapter.addTab(tab1, FirstFragment.class);
mTabsAdapter.addTab(tab2, SecondFragment.class);

无论如何,问题还是一样。

这里是 actionbar_tabs_pager.xml

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

【问题讨论】:

    标签: android view fragment android-viewpager


    【解决方案1】:

    已解决!

    在 TabsAdapter 中覆盖 instantiateItem() 并将 ViewPager 添加为 FragmentTransaction 中的 ContainerViewID 成功了!

    这是整个 FragmentActivity 的功能!

    import java.util.ArrayList;
    import android.app.Activity;
    import android.app.FragmentManager;
    import android.app.FragmentManager.OnBackStackChangedListener;
    import android.content.Context;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v4.app.ActionBar;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.support.v4.app.FragmentPagerAdapter;
    import android.support.v4.app.FragmentTransaction;
    import android.support.v4.app.ActionBar.Tab;
    import android.support.v4.app.SupportActivity;
    import android.support.v4.view.ViewPager;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.View.OnClickListener;
    import android.widget.TextView;
    
    /**
     * Demonstrates combining the action bar with a ViewPager to implement a tab UI
     * that switches between tabs and also allows the user to perform horizontal
     * flicks to move between the tabs.
     */
    public class ActionBarTabsPager extends FragmentActivity implements SecondFragment.OnButtonClickedXListener{
        ViewPager  mViewPager;
        TabsAdapter mTabsAdapter;
        FragmentManager fm;
    
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            Log.i("ONCREATE START","ONCREATE START");
    
    
            setContentView(R.layout.actionbar_tabs_pager);
    
    
            if (savedInstanceState == null) {
    
    
                Fragment newFragment = new FirstFragment();
                Fragment newFragment2 = new SecondFragment();
    
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.add(R.id.pager, newFragment, "FirstFragment");
                ft.add(R.id.pager, newFragment2, "SecondFragment");
                ft.commit();
    
    
           }
    
            getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    
            ActionBar.Tab tab1 = getSupportActionBar().newTab().setText("Fragment 1");
            ActionBar.Tab tab2 = getSupportActionBar().newTab().setText("Fragment 2");
            //ActionBar.Tab tab3 = getSupportActionBar().newTab().setText("Fragment 1");
            //ActionBar.Tab tab4 = getSupportActionBar().newTab().setText("Fragment 2");
    
            mViewPager = (ViewPager)findViewById(R.id.pager);
            mTabsAdapter = new TabsAdapter(this, getSupportActionBar(), mViewPager);
    
                mTabsAdapter.addTab(tab1, FirstFragment.class);
                mTabsAdapter.addTab(tab2, SecondFragment.class);//LoaderCursorSupport.CursorLoaderListFragment.class);
                //mTabsAdapter.addTab(tab3, FirstFragment.class);//LoaderCustomSupport.AppListFragment.class);
                //mTabsAdapter.addTab(tab4, SecondFragment.class);//LoaderThrottleSupport.ThrottledLoaderListFragment.class);
    
    
    
            if (savedInstanceState != null) {
                getSupportActionBar().setSelectedNavigationItem(savedInstanceState.getInt("index"));
            }
    
            Log.i("ONCREATE END","ONCREATE END");
    
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            Log.i("onSaveInstanceState START","onSaveInstanceState START");
            super.onSaveInstanceState(outState);
            outState.putInt("index", getSupportActionBar().getSelectedNavigationIndex());
            Log.i("onSaveInstanceState END","onSaveInstanceState END");
    
        }
    
        /**
         * This is a helper class that implements the management of tabs and all
         * details of connecting a ViewPager with associated TabHost.  It relies on a
         * trick.  Normally a tab host has a simple API for supplying a View or
         * Intent that each tab will show.  This is not sufficient for switching
         * between pages.  So instead we make the content part of the tab host
         * 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
         * view to show as the tab content.  It listens to changes in tabs, and takes
         * care of switch to the correct paged in the ViewPager whenever the selected
         * tab changes.
         */
        public class TabsAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {
            private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<String> mTabs = new ArrayList<String>();
            private FragmentTransaction mCurTransaction = null;
    
    
            public TabsAdapter(FragmentActivity activity, ActionBar actionBar, ViewPager pager) {
                super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = actionBar;
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
    
    
            }
    
            public void addTab(ActionBar.Tab tab, Class<?> clss) {
                Log.i("addTab","addTab");
    
                mTabs.add(clss.getName());
                mActionBar.addTab(tab.setTabListener(this));
                notifyDataSetChanged();
            }
    
            @Override
            public int getCount() {
                return mTabs.size();
            }
    
            @Override
            public Object instantiateItem(View container, int position) {
                if (mCurTransaction == null) {
                    mCurTransaction = getSupportFragmentManager().beginTransaction();
                }
                // TODO Auto-generated method stub
                Fragment fragment = getItem(position);
    
                if (fragment!=null){
                    Log.i("Fragment Found!","Fragment Found! "+fragment.getTag());
                    mCurTransaction.attach(fragment);
                    }
    
    
                return fragment;//super.instantiateItem(container, position);
            }
    
            @Override
            public Fragment getItem(int position) {
                Log.i("getItem","getItem");
    
                if (position==0)
                    {Log.i("position=0","position=0");
                    return getSupportFragmentManager().findFragmentByTag("FirstFragment");}
    
                else if (position==1)
                {Log.i("position=1","position=1");
                    return getSupportFragmentManager().findFragmentByTag("SecondFragment");}
    
                else return null;//Fragment.instantiate(mContext, mTabs.get(position), null);
    
            }
    
    
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }
    
            @Override
            public void onPageSelected(int position) {
                mActionBar.setSelectedNavigationItem(position);
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
            }
    
            @Override
            public void onTabSelected(Tab tab, FragmentTransaction ft) {
                mViewPager.setCurrentItem(tab.getPosition());
    
            }
    
            @Override
            public void onTabReselected(Tab tab, FragmentTransaction ft) {
            }
    
            @Override
            public void onTabUnselected(Tab tab, FragmentTransaction ft) {
            }
    
    
        }
    
        @Override
        public void OnButtonClickedX(View v) {
    
            if (v==findViewById(R.id.button1)){
                Log.i("TRIGGERED","TRIGGERED");
    
                FirstFragment ff = (FirstFragment) getSupportFragmentManager().findFragmentByTag("FirstFragment");
    
                View root = ff.getView();
                TextView tv = (TextView) root.findViewById(R.id.textView1);
                Log.i("Text before Edit",""+tv.getText());
                      tv.setText("MODIFIED");
                      Log.i("Text after Edit",""+tv.getText());
    
    
    
    
            }
            // TODO Auto-generated method stub
    
        }
    
    
    
    
    
    }
    

    感谢 vbsteven!

    【讨论】:

      【解决方案2】:

      我假设您在屏幕上看到的片段不是您使用标签“FirstFragment”和“SecondFragment”手动添加的片段,而是您的 TabsAdapter 的 getItem 方法添加的片段。

      如果您查看它的实现,它会实例化新的 Fragments。

          @Override
          public Fragment getItem(int position) {
              return Fragment.instantiate(mContext, mTabs.get(position), null);
          }
      

      这些新创建的 Fragment 使用 FragmentPagerAdapter(TabsAdapter 扩展)中生成的自定义标签添加到 FragmentManager

      【讨论】:

      • 我注释掉了 FragmentTransaction,实际上 UI 是正确创建的。所以当 mTab​​sAdapter.addTab(tab1, FirstFragment.class); mTabsAdapter.addTab(tab2, SecondFragment.class);叫做。那么如何在不让它们重新创建实例的情况下取回 FirstFragment 和 SecondFragment 的实例呢?
      • 您必须重写 instantiateItem/getItem 方法,以便它们使用您的片段而不是创建新片段。您可能最好创建一个新的 PagerAdapter 子类(查看 FragmentPagerAdapter 的源代码以供参考),该子类考虑到现有的片段。
      【解决方案3】:

      我的猜测是,这是“重叠”片段的情况——对于那些第一次尝试片段的人来说并不少见。每次你重新显示一个片段(显示一个片段,显示另一个片段,然后回到你显示的第一个片段),你在可见片段后面创建一个新片段。 “镜像片段”仍然在顶部,挡住了您对它后面的片段的看法。只有滚动那个片段,你才能看到后面的片段确实得到了更新。

      大多数情况下,您只是在 FragmentActivity 中重复您在 XML 中所做的事情。发布您的布局 xml,以便片段专家可以更好地诊断您的问题。

      【讨论】:

      • 我不认为是布局问题,因为片段没有在 xml 中声明,它们都是从源代码添加的.. TabsAdapter 中可能有一些东西,但我无法弄清楚。 .
      【解决方案4】:

      请同时发布 actionbar_tabs_pager.xml。

      不知道它是否能解决您的问题,但在这部分代码中,您为两个片段添加 FirstFragment()...

      Fragment newFragment = new FirstFragment();
      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      ft.add(R.id.abs__custom, newFragment, "FirstFragment").commit();
      
      Fragment newFragment2 = new FirstFragment();
      FragmentTransaction ft2 = getSupportFragmentManager().beginTransaction();
      ft2.add(R.id.abs__custom, newFragment2, "SecondFragment").commit();
      

      ...你可以这样写更简单:

      FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
      ft.add(R.id.abs__custom, newFragment, "FirstFragment");
      ft.add(R.id.abs__custom, newFragment2, "SecondFragment");
      ft.commit();
      

      【讨论】:

      • 它不能解决问题,但是感谢您指出这一点。事实证明,即使将“0”分配给布局的 ft.add() 函数,如 'ft.add(0, newFragment, "FirstFragment");'不影响渲染。我猜'mTabsAdapter.addTab(tab1, FirstFragment.class);'是什么呈现布局,而不是事务。
      • 您在 xml 中哪里定义了“R.id.abs__custom”?
      • R.id.abs__custom.xml 不相关,请看编辑!
      猜你喜欢
      • 1970-01-01
      • 2014-04-18
      • 1970-01-01
      • 2013-09-06
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      相关资源
      最近更新 更多