【问题标题】:Stuck at adding/changing fragments in android studio卡在 android studio 中添加/更改片段
【发布时间】:2017-08-01 15:32:11
【问题描述】:

即使我在 Google 上进行了广泛搜索,我也找不到解决问题的方法。我是编程新手,所以请在你的回答中考虑到这一点。

我在底部有一个主活动和一个菜单栏。由于菜单栏是可滚动的,并且我希望它适用于所有不同的屏幕,我发现我可以 - 而不是为新活动制定意图 - 只需在现有屏幕顶部放置一个片段(并省去菜单栏)。

但我无法以编程方式打开该片段。我尝试了以下方法,但它甚至无法识别 FrameLayout 的 ID。

我试图用片段替换主要活动的 xml 文件中的 FrameLayout:

    FragmentManager fragmentManager = getSupportFragmentManager();
    android.support.v4.app.FragmentTransaction ft =
    fragmentManager.beginTransaction();

    ft.replace(R.id.idOfFrameLayout, new nameOfFragmentClass());
    ft.commit();

编辑:

在我将 OnFragmentInteractionListener 实现到 Main Activity 后它就可以工作了。谢谢大家!

【问题讨论】:

  • 所以它在抱怨R.id.idOfFrameLayout?能贴出错误信息和布局文件吗?
  • 您的第一个Fragment 是否也动态加载?
  • 现在框架布局 ID 正在工作。一定是输入了错误的东西。但是现在应用程序只是在启动时崩溃(我尝试在 onCreate 方法中执行该代码。由于我是一个该死的新手,很可能我做错了非常基本的事情,因为我没有找到关于 Fragments 的合适教程.
  • 上述代码,是来自activity还是fragment?

标签: java android


【解决方案1】:

我的原始答案建议使用add 而不是replace 进行片段交易。从那以后,我了解到在这种情况下可以使用任何一种。有关差异的更多信息,请参阅thisthisthis

由于我的添加/替换想法没有根据,我已将答案更改为简单的片段教程。一个片段从一个活动膨胀。我已经包含了 Fragment 到 Activity 通信的代码(OPs 问题的原因),但是如果不需要的话,可以删除哪些内容。 Activity 中唯一要做的事情是启动 Fragment,然后从该 Fragment 接收消息。 Fragment 有一个按钮,可以将消息发送回 Activity。然后将记录该消息。

在这两个类中,如果不需要从 Fragment 到 Activity 的通信,请删除任何标记为 TODO 的内容:

// this is what controls whether you use a Fragment from the support library
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class SimpleActivity extends AppCompatActivity
//      TODO: delete "implements SimpleFragment.OnFragmentInteractionListener" from this
//      line (leave the '{')
        implements SimpleFragment.OnFragmentInteractionListener {

    private static final String TAG = SimpleActivity.class.getSimpleName();

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

        SimpleFragment fragment = new SimpleFragment();

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
            .add(R.id.fragment_container, fragment)
            .commit();
    }

    // TODO: this entire method can be deleted
    @Override
    public void onFragmentInteraction(String message) {
        // This is where you can act on the message from the Fragment.  You would do 
        //  things that are done from an Activity or you may pass the message on 
        //  to another Fragment.
        Log.d(TAG, message);
    }
}

大部分导入语句都没有显示,我留下这个是为了表示使用支持库

import android.support.v4.app.Fragment;

public class SimpleFragment extends Fragment {
    private OnFragmentInteractionListener mListener;    // TODO: delete this line

    public SimpleFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_simple, container, false);

        Button button = (Button)rootView.findViewById(R.id.msg_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // TODO: delete these 3 lines, do something else with the button click
                if (mListener != null) {
                    mListener.onFragmentInteraction("Message from Fragment");
                }
            }
        });

        return rootView;
    }

    // TODO: this entire method can be deleted
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    // TODO: this entire method can be deleted
    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    // TODO: this entire method can be deleted
    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(String message);
    }
}

现在是布局文件。第一个activity_simple.xml

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

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/fragment_container"
        >
    </FrameLayout>
</android.support.constraint.ConstraintLayout>

然后是fragment_simple.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Info to Activity"
        android:id="@+id/msg_button"
        />
</RelativeLayout>

这是一个非常基本的示例。 Here 是更全面的 Fragment 使用指南。

【讨论】:

  • 感谢您的回答。不幸的是,将“替换”更改为“添加”不起作用,应用程序仍然崩溃。我阅读了教程,我注意到(之前已经)是,我不能使用那里给出的代码。它显示一条错误消息,说明“必需的 [...].v4.[...]”,因此我使用了“android.support.v4.app”。 “FragmentTransaction”前面(它是下拉菜单中的一个选项,使编译器错误消失)。我也不能使用“getFragmentManager”,因为它显示相同的“v4”错误消息。
  • 是的。虽然 Google 在其指南中的示例代码作为一般指南非常棒,但它有时很旧,有时甚至有错误(我认为他们只是输入代码而没有编译和运行有时)。 “...support.v4...”支持包一开始可能会令人困惑(有时稍后也会)。通常,当它们可用时,您想使用它们。最好在文件顶部使用“导入”来处理它们,但这也可以。
  • “您可能只需要更改一行”我说可能是因为您的代码也可能存在其他问题。您可以从崩溃中发布您的堆栈跟踪吗?您将希望将此作为对问题的编辑(这也适用于布局文件请求)与评论中。
  • 在您询问我的“stacktrace”后,我查看了 Android Monitor(因为我不知道 stacktrace 是什么并搜索了它)。在那里我发现一条红色消息告诉我,我必须实现 OnFragmentInteractionListener + 它的 onFragmentInteraction 方法。我做到了,现在它可以工作了。
  • 所以它在 onAttach() 中失败了,因为您的 Activity 没有实现监听器。第一次使用片段时的常见错误。以供将来参考,仅当您计划向活动(或另一个片段)发送信息时才需要它。如果您的所有信息都是 Activity->Fragment,您可以删除 onAttach() 方法,从您的 Fragment 中删除 interface 并跳过将其放入您的 Activity。很好奇,现在它正在工作,它是否与replace()一起工作?
【解决方案2】:

当你使用 'replace' 方法时,你需要做 3 件事:

1- 容器 id,即存放片段视图的视图。 2-您要使用的片段实例和 3- 片段实例的标签,但这是可选的。

鉴于此,假设您的 Activity 具有以下布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<android.support.design.widget.AppBarLayout
    ...
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="?android:attr/windowBackground"
    app:menu="@menu/navigation" />
</android.support.design.widget.CoordinatorLayout>

id 为“container”的 FrameLayout 是持有视图,所以这就是你必须使用的 id:

ft.replace(R.id.container, new nameOfFragmentClass());

【讨论】:

  • 我将这些值放入 replace 方法,但是当我开始执行它时我的应用程序崩溃了。
【解决方案3】:

我建议使用这个库来管理片段:

FragmentManagerAndroid

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-12
    • 2018-03-22
    • 1970-01-01
    • 2017-10-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多