2012-02-05 63 views
0

我想更新片段中的TextView,单击另一个片段上的按钮。从另一个片段更新ViewPager中的TextView

实际上,我对Activity执行了回调函数,它确实有效,因为Logcat报告TextView中的文本已被更改。问题是第一个片段中显示的Textview未更新为新值!这就像片段需要更新或东西...

这里的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 

    } 





} 

FirstFragment:

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> 

编辑:

即使改变为0()的ContainerViewId在ft.add不最终渲染中的影响。所以我想渲染管理通过

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" 
/> 

回答

0

我的猜测是,它是此的“重叠”片段的情况下 - 并不少见,这些尝试片段首次。每次你重新显示一个片段(显示一个片段,显示另一个片段,然后返回到你显示的第一个片段),你就会在可见片段后面创建一个新的片段。 “镜像片段”保留在顶部,阻止您查看其后面的片段。只有通过滚动该片段才能看到背后的片段确实得到更新。

大多数情况下,这只是您在FragmentActivity中重复执行XML操作的情况。发布您的布局xml,以便片段专业人员可以更好地诊断您的问题。

+0

我不认为是布局问题,因为片段没有在xml中声明,他们都是从源添加..可能有一些TabsAdapter,但我不知道这一点.. – Mariux 2012-02-05 20:03:35

0

请发布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

它doesn'解决这个问题,不过谢谢你指出这个问题。 (0,newFragment,“FirstFragment”);''这个结果,即使给布局的ft.add()函数分配了“0”,如'ft.add(0,newFragment,“FirstFragment”不影响渲染。 我猜'mTabsAdapter.addTab(tab1,FirstFragment.class);'是什么呈现布局,而不是交易。 – Mariux 2012-02-06 16:12:55

+0

你在xml中定义了“R.id.abs__custom”? – ramdroid 2012-02-07 12:29:32

+0

R.id.abs__custom.xml不相关,请看看编辑! – Mariux 2012-02-09 10:37:24

2

我假设你看到屏幕上的碎片是不是你手动标签“FirstFragment”和“SecondFragment”,而是被添加的片段添加片段通过TabsAdapter的getItem方法。

如果你看看它的实现,它会实例化新的碎片。

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

这些新创建的片段将被添加到FragmentManager与

+0

我注释掉了FragmentTransaction,实际上UI已经正确创建。因此,可能在调用getItem()时,会调用这个函数: mTab​​sAdapter.addTab(tab1,FirstFragment.class); mTab​​sAdapter.addTab(tab2,SecondFragment.class); 被调用。 那么我怎样才能找回FirstFragment和SecondFragment的实例而不让它们重新创建一个实例呢? – Mariux 2012-02-09 13:49:57

+1

您必须重写instantiateItem/getItem方法,以便它们使用碎片而不是创建新碎片。 通过创建PagerAdapter的新子类(查看FragmentPagerAdapter的参考源),可能会考虑到现有片段。 – vbsteven 2012-02-09 13:54:20

+0

有没有任何示例或源代码的应用程序来理解这一点? – Mariux 2012-02-09 15:14:38

4

解决了FragmentPagerAdapter(其中TabsAdapter扩展)生成的自定义标签!

覆盖instantiateItem() in TabsAdapter并在FragmentTransaction中添加ViewPager作为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!