2012-02-05 43 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!

相關問題