2017-05-05 128 views
0

我已经阅读了无数SO关于findFragmentByTag()返回null的问题的文章,并且在几天之后,我仍然无法使其工作。所以我听说要发表我自己的问题。又一次findFragmentByTag()返回null

我有一个容器和三个片段。我希望能够从A - > B - > C - > A - >等或向后滑动/滑动。也就是说,左滑动或右滑动循环浏览碎片面板。
我有这一切工作。但我的问题是,一旦我滑过完整循环从A返回到A,与TextView字段的所有连接都不再有效(这些片段中有许多实时更新文本字段)。这是更新不再存在,我不能再看到对领域的变化;我可以setText("foo")到一个字段,但新值不再显示。当片段出现时,不再有任何文本视图更新。就好像片段的原始实例在某处丢失,并且显示的实例是新实例。 基于logcat的结果,我认为这是发生。事实上,findFragmentByTag是总是返回null,因此代码每次刷新时都会创建新的片段。

我想坚持每个实例(A,B和C),以便它们保持状态,并且在我滑过片段时可以看到正在进行的更新。 以下是完整的代码文件:

package com.company.myApp; 

import android.app.Activity; 
import android.app.Fragment; 
import android.app.FragmentTransaction; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.GestureDetector; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 

public class Fragment_ProgressBar extends Fragment { 
    final static String TAG = "Fragment_ProgressBar"; 
    final static String FRAGMENT_TAG_SUMMARY  = "Fragment_Summary"; 
    final static String FRAGMENT_TAG_PROGRESSBAR = "Fragment_ProgressBar"; 
    final static String FRAGMENT_TAG_TIME = "Fragment_Time"; 
    final static String DIRECTION_LEFT = "DIRECTION_LEFT"; 
    final static String DIRECTION_RIGHT = "DIRECTION_RIGHT"; 
    public final static String CURRENT_FRAGMENT = FRAGMENT_TAG_PROGRESSBAR; 
    final Fragment thisFragment = this; 

    public Fragment_ProgressBar(){} 

    @Override 
    public View onCreateView(LayoutInflater inflater, 
          ViewGroup container, 
          Bundle savedInstanceState) { 

     final GestureDetector gesture = new GestureDetector(getActivity(), 
       new GestureDetector.SimpleOnGestureListener() { 

        @Override 
        public boolean onDown(MotionEvent e) { 
         return true; 
        } 

        @Override 
        public boolean onFling(MotionEvent event1, 
              MotionEvent event2, 
              float velocityX, 
              float velocityY) { 
         final int SWIPE_MIN_DISTANCE = 120; 
         final int SWIPE_MAX_OFF_PATH = 250; 
         final int SWIPE_THRESHOLD_VELOCITY = 200; 
         try { 
          if (Math.abs(event1.getY() - event2.getY()) > SWIPE_MAX_OFF_PATH) 
           return false; 
          if (event1.getX() - event2.getX() > SWIPE_MIN_DISTANCE 
            && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
           Log.i(TAG, "Right to Left"); 
           showFragment_RightToLeft(FRAGMENT_TAG_TIMECIRCLE); 
          } else if (event2.getX() - event1.getX() > SWIPE_MIN_DISTANCE 
            && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
           Log.i(TAG, "Left to Right"); 
           showFragment_LeftToRight(FRAGMENT_TAG_SUMMARY); 
          } 
         } catch (Exception e) { 
          // nothing 
         } 
         return super.onFling(event1, event2, velocityX, velocityY); 
        } 
       }); 

     View view = inflater.inflate(R.layout.fragment_progress_bar, container, false); 
     view.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       return gesture.onTouchEvent(event); 
      } 
     }); 
     // Inflate the layout for this fragment 
     return view; 
    } 

    private Fragment getNewFragment(String name){ 
     Log.i(TAG,String.format("Fragment (%s) not found; creating new instance.", name)); 
     switch (name) { 
      case FRAGMENT_TAG_SUMMARY: 
       return new Fragment_Summary(); 
      case FRAGMENT_TAG_PROGRESSBAR: 
       return new Fragment_ProgressBar(); 
      case FRAGMENT_TAG_TIME: 
       return new Fragment_Time(); 
     } 
     return null; 
    } 

    private void showFragment_LeftToRight(String nextFragmentNameTag) 
    { 

     Fragment nextFragment = getChildFragmentManager().findFragmentByTag(nextFragmentNameTag); 
     if (nextFragment == null) 
      nextFragment = getNewFragment(nextFragmentNameTag); 
     if (nextFragment == null) 
      return; 

     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     ft.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_out_right); 
     ft.remove(thisFragment); 
     ft.add(R.id.overview_fragment_container, nextFragment, nextFragmentNameTag); 
     ft.addToBackStack(null); 
     ft.commit(); 
     getFragmentManager().executePendingTransactions(); 

    } 
    private void showFragment_RightToLeft(String nextFragmentNameTag) 
    { 
     Fragment nextFragment = getChildFragmentManager().findFragmentByTag(nextFragmentNameTag); 
     if (nextFragment == null) 
      nextFragment = getNewFragment(nextFragmentNameTag); 
     if (nextFragment == null) 
      return; 

     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     ft.setCustomAnimations(R.animator.slide_in_right, R.animator.slide_out_left); 
     ft.replace(R.id.overview_fragment_container, nextFragment, nextFragmentNameTag); 
     ft.addToBackStack(null); 
     ft.commit(); 
     getFragmentManager().executePendingTransactions(); 

    } 

} 
+0

我试着在主要活动中放置findFragmentByTag()调用,并没有什么区别。仍为空。 – Hephaestus

+1

你为什么要寻找一个私人片段管理器中的片段getChildFragmentManager(),然后在主片段管理器中进行处理getFragmentManager()?其次,当你打电话去除和替换时,你如何期望片段仍然存在? – Distjoy

+0

无知!答案很简单,无知!我只是改变了getChildManager,它现在可以工作。谢谢! – Hephaestus

回答

2

首先你要找的片段,好像他们是连接作为子片段的Fragment_ProgressBar,所有的片段仍然是由活性片段经理管理的,所以你在错误的地方寻找碎片。

其次,您每次在执行事务时调用FragmentTransaction.remove()FragmentTransaction.replace()时,都会从片段管理器中删除旧片段。我还建议你添加/重新附加新的片段并分离旧片段(该片段已从UI中删除,但其状态仍由片段管理器主动管理)。

+0

如果我想添加一个新的片段*和*存储旧的片段,那么正确的顺序是什么?在我添加新的片段之前,我不需要“移除”或“替换”旧的片段吗? – Hephaestus

+1

如果您调用'remove'或使用'replace',那么片段管理器将不会存储旧片段(除非您想保留片段实例,否则可能无法顺利流动)。只需分离旧的,然后添加(新)/重新附加(预先存在)一个。 – Distjoy