尝试在按钮上单击另一个片段替换main_activity片段

时间:2016-04-24 02:18:11

标签: java android xml fragment fragmenttransaction

我正在尝试在欢迎屏幕上创建一个按钮,当单击时,会启动一个片段。

activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/touch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="me.alexoladele.quotebook.MainActivity">

    <TextView
        android:id="@+id/welcome_screen_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_gravity="center_horizontal|top"
        android:layout_marginTop="144dp"
        android:gravity="center"
        android:text="The QuoteBook hosts Kanye West quotes. Enjoy"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="36dp" />

    <Button
        android:id="@+id/start_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="47dp"
        android:clickable="true"
        android:elegantTextHeight="false"
        android:enabled="true"
        android:text="Start!" />

</FrameLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {
int count = 0;
final QuoteFragment quoteFragment = new QuoteFragment();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    Button startButton = (Button) findViewById(R.id.start_button);
    if (startButton != null)
        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
              quoteFragment.startSecondFragment();

            }
        });



    }



}

quote_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_height="match_parent"     android:id="@+id/real_quote_frag">
<fragment
    android:id="@+id/quote_frag"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="me.alexoladele.quotebook.QuoteFragment"
    tools:layout="@layout/activity_main">
<TextView
    android:text="@string/tap_screen"
    android:id="@+id/quote"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="sans-serif-medium"
    android:textSize="26sp"
    android:gravity="center"
    android:layout_gravity="center"
    android:textColor="#a6a6a6" />

<TextView
    android:text="@string/quotist_name"
    android:visibility="visible"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="sans-serif-medium"
    android:textSize="26sp"
    android:gravity="center"
    android:textColor="#585858"
    android:layout_gravity="center_horizontal|bottom"
    android:id="@+id/person" />
</fragment>

QuoteFragment.java:

public class QuoteFragment extends Fragment {
int count = 0;

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

    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.quote_fragment, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    FrameLayout touch = (FrameLayout) getView().findViewById(R.id.touch);
    final TextView quoteText = (TextView)  getView().findViewById(R.id.quote);

    // Makes quotes array
    String[] quotes = {
            "Quotes Placeholder"
    };

    // Put quotes array into arraylist
    final List<String> quoteList = new ArrayList<>(Arrays.asList(quotes));

    //
    if (touch != null)
        touch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (count >= quoteList.size()) {
                    count = 0;
                }
                Quote q = new Quote("");
                q.setQuote(quoteList.get(count));

                quoteText.setText(q.getQuote());
                count++;
            }
        });

}

public void startSecondFragment() {
    QuoteFragment myFragment = new QuoteFragment();
    FragmentManager manager = getFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.real_quote_frag, myFragment, "Quote");
    transaction.addToBackStack(null);
    transaction.commit();

    }
}

我收到此错误:

 FATAL EXCEPTION: main
                                                                             java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' on a null object reference
                                                                              at me.alexoladele.quotebook.QuoteFragment.startSecondFragment(QuoteFragment.java:91)
                                                                              at me.alexoladele.quotebook.MainActivity$1.onClick(MainActivity.java:23)
                                                                              at android.view.View.performClick(View.java:4756)
                                                                              at android.view.View$PerformClick.run(View.java:19761)
                                                                              at android.os.Handler.handleCallback(Handler.java:739)
                                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                              at android.os.Looper.loop(Looper.java:135)
                                                                              at android.app.ActivityThread.main(ActivityThread.java:5253)
                                                                              at java.lang.reflect.Method.invoke(Native Method)
                                                                              at java.lang.reflect.Method.invoke(Method.java:372)
                                                                              at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)
                                                                              at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:695)
                                                                              at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:114)Bridge.java:114)

有人能帮助我弄清楚我做错了什么,并指出我更有效的处理方法吗?

1 个答案:

答案 0 :(得分:0)

问题

您尚未将QuoteFragment附加到MainActivity,这意味着getFragmentManager()中的QuoteFragment来电将返回null,因为它基本上会调用它附加到的父活动,在您的情况下将为null,因此为NullPointerException。 (仅仅保留对片段的引用,因为你的字段是不够的)

更好的方法

这就是强烈推荐(你真的应该让你的生活更轻松),你从Fragment管理Activity

目前您正在QuoteFragment进行分段交易,而应该在MainActivity中进行管理。

所以这就是你的MainActivity

中的样子
Button startButton = (Button) findViewById(R.id.start_button);
    if (startButton != null)
        startButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startSecondFragment(); // start your fragment from MainActivity
        }
    });

// This method will be in charge of handling your second fragment
private void startSecondFragment() {
    FragmentManager manager = getFragmentManager();
    FragmentTransaction transaction = manager.beginTransaction();
    transaction.replace(R.id.real_quote_frag, quoteFragment, "Quote");
    transaction.addToBackStack(null);
    transaction.commit(); 
}

更新:

为了帮助您更好地理解,我的活动和片段结构如下所示:

<强> activity_main.xml中

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- The view where I place my fragment -->
    <FrameLayout
        android:id="@+id/fragmentContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java 我替换我的片段:

FragmentManager fragmentManager = getSupportFragmentManager();

// Note how I place my fragment into fragmentContent layout
fragmentManager.beginTransaction().replace(R.id.fragmentContent, fragment).commit();

<强> fragment_layout.xml

请注意我如何使用单独的片段布局xml文件将 INTO fragmentContent放在`activity_main.xml1

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.forcasie.joelmin.Fragment.HomeFragment">

    <!-- TODO: Update blank fragment layout -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">
        <TextView
            android:textStyle="bold"
            android:textSize="25sp"
            android:text="@string/homeMessage"
            android:gravity="center_horizontal"
            android:layout_marginTop="40dp"
            android:layout_gravity="center_horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        </LinearLayout>

</FrameLayout>

Fragment.java 其中我 SET 具有上述布局文件的片段的实际布局:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment

    return inflater.inflate(R.layout.fragment_layout, container, false);
}