简体   繁体   English

如何动态地使此子片段的TextView可见/不可见?

[英]How do I dynamically make this child Fragment's TextView visible/invisible?

I have a main Activity containing a parent Fragment, which in turn contains a child Fragment. 我有一个包含父片段的主活动,而父片段又包含了一个子片段。 I am trying to make a TextView in the child Fragment visible/invisible dynamically. 我试图使子片段中的TextView动态可见/不可见。

activity_main.xml activity_main.xml中

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This text belongs to the Activity"
        android:id="@+id/textView"/>

    <FrameLayout
        android:id="@+id/parent_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

fragment_parent.xml fragment_parent.xml

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


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This text belongs to the parent fragment"
        android:id="@+id/textView"/>


    <FrameLayout
        android:id="@+id/child_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

fragment_child.xml fragment_child.xml

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This text belongs to the child fragment"
        android:id="@+id/textView"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="But make this text visible dynamically!"
        android:id="@+id/make_this_text_visible"
        android:visibility="invisible"/>
</LinearLayout>

MainActivity.java MainActivity.java

public class MainActivity extends AppCompatActivity {
    public static final String PARENT_TAG = "parent_tag";
    private ParentFragment mParentFragment;

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

        if (savedInstanceState == null) {
            mParentFragment = ParentFragment.newInstance();
            getSupportFragmentManager().beginTransaction().replace(R.id.parent_container, mParentFragment, PARENT_TAG).commit();
        }
        else {
            mParentFragment = (ParentFragment) getSupportFragmentManager().findFragmentByTag(PARENT_TAG);
        }
    }
}

ParentFragment.java ParentFragment.java

public class ParentFragment extends Fragment {
    public static final String CHILD_TAG = "child_tag";
    private ChildFragment mChildFragment;
    private List<Integer> mList;

    public static ParentFragment newInstance() {

        Bundle args = new Bundle();

        ParentFragment fragment = new ParentFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_parent, container, false);
        mList = new ArrayList<Integer>();

        if (savedInstanceState == null) {
            mChildFragment = ChildFragment.newInstance();
            getChildFragmentManager().beginTransaction().replace(R.id.child_container, mChildFragment, CHILD_TAG).commit();
        }
        else {
            mChildFragment = (ChildFragment) getChildFragmentManager().findFragmentByTag(CHILD_TAG);
        }
        getChildFragmentManager().executePendingTransactions(); //doesn't seem to do anything!
        doStuff();

        return view;
    }

    void doStuff() {
        mList.add(4); //pretend this is actually querying a database.
        //for simplicity it just receives a single 4.

        if (mList.size() > 0) { //the list is not empty, display the text!
            mChildFragment.setTextVisible(); //error! the textivew of the child fragment is null right now
        }
        else {
            mChildFragment.setTextInvisible(); //error! the textivew of the child fragment is null right now
        }
    }
}

ChildFragment.java ChildFragment.java

public class ChildFragment extends Fragment {
    private TextView mTextView;

    public static ChildFragment newInstance() {

        Bundle args = new Bundle();

        ChildFragment fragment = new ChildFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        mTextView = (TextView) view.findViewById(R.id.make_this_text_visible);
        return view;
    }

    public void setTextVisible() {
        mTextView.setVisibility(View.VISIBLE);
    }
    public void setTextInvisible() {
        mTextView.setVisibility(View.INVISIBLE);
    }
}

How can I ensure that the child fragment is formed by the time I call doStuff() in the ParentFragment? 如何确保在我在ParentFragment中调用doStuff()时形成了子片段?

What I would do is keep the state of the text view visibility so it can be updated properly once the view has been created if it hasn't been already. 我要做的是保持文本视图可见性的状态,以便在尚未创建视图后就可以对其进行正确更新。 Instead of separate methods for setTextVisible() and setTextInvisible have a single method setTextVisibile(boolean isVisible) and implement it as follows: 不用setTextVisible()setTextInvisible的单独方法, setTextVisible()使用单个方法setTextVisibile(boolean isVisible)并按以下方式实现:

public class ChildFragment extends Fragment {
    private TextView mTextView;
    private boolean mIsTextVisible;

    public static ChildFragment newInstance() {
        Bundle args = new Bundle();
        ChildFragment fragment = new ChildFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        mTextView = (TextView) view.findViewById(R.id.make_this_text_visible);
        setTextVisible(mIsTextVisible);

        return view;
    }

    public void setTextVisible(boolean isVisible) {
        mIsTextVisible = isVisible;
        if(mTextView != null) {
            mTextView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
        }
    }
}

and then in the parent fragment you can call doStuff() without worrying about the current state of the views in the ChildFragment since mIsTextVisible is properly set. 然后在父片段可以调用doStuff()而不必担心在视图的当前状态ChildFragment因为mIsTextVisible设置正确。 If the mTextView is null at the time setTextVisible() is called the visibility will still be properly set in onCreateView() . 如果在mTextView setTextVisible()mTextView为null,则仍将在onCreateView()正确设置可见性。

Just take care to save and restore the mIsTextVisible flag when the fragment is recreated such as when the device is rotated. 在重新创建片段(例如旋转设备)时,请小心保存并还原mIsTextVisible标志。


Alternative Answer Using A Callback 使用回调的替代答案

Using callbacks update the ParentFragment to implement ChildFragment.OnViewCreatedListener and its method. 使用回调更新ParentFragment以实现ChildFragment.OnViewCreatedListener及其方法。

public class ParentFragment extends Fragment
    implements ChildFragment.OnViewCreatedListener {

    @Override
    public void onViewCreated() {
        doStuff();
    }
}

And then in ChildFragment 然后在ChildFragment

public class ChildFragment extends Fragment {
    public interface OnViewCreatedListener {
        void onViewCreated();
    }

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

        View view = inflater.inflate(R.layout.fragment_child, container, false);
        mTextView = (TextView) view.findViewById(R.id.make_this_text_visible);

        if(getParentFragment() instanceof OnViewCreatedListener) {
            ((OnViewCreatedListener) getParentFragment()).onViewCreated();
        } else if (getActivity() instanceof OnViewCreatedListener) {
            ((OnViewCreatedListener) getActivity()).onViewCreated();
        }

        return view;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM