简体   繁体   中英

android fragments problems

i wrote a toDO list for my android class. It totally works , but now i want to display the todo list on a fragment ( so it can be its on tab). but when i tried making the fragment , i get a weird error when i try to run it. apparently the error comes from my main activity . so the way i have it set up is that, my main activity has a button that opens the fragment that has all the TOdolist stuff in it. but when i run it on my phone i get a unfortunately TodoList ha stopped as soon as it runs. the error is get is

06-10 22:21:51.284    5302-5302/com.example.mike.todolist D/AbsListView﹕ Get MotionRecognitionManager
06-10 22:21:51.304    5302-5302/com.example.mike.todolist D/AndroidRuntime﹕ Shutting down VM
06-10 22:21:51.304    5302-5302/com.example.mike.todolist W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x417c2898)
06-10 22:21:51.314    5302-5302/com.example.mike.todolist E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at com.example.mike.todolist.ToDoFragment.onCreateView(ToDoFragment.java:38)
            at android.app.Fragment.performCreateView(Fragment.java:1699)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075)
            at android.app.BackStackRecord.run(BackStackRecord.java:682)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1455)
            at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5455)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
            at dalvik.system.NativeStart.main(Native Method)




my main activity look like

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.view.View;



public class MainActivity extends ListActivity {


    @Override
    public void onCreate(Bundle savedInstanceState) {

        setContentView(R.layout.todo_main_activity);
        super.onCreate(savedInstanceState);
        Button button1 = (Button) findViewById(R.id.fragButton);
        button1.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                FragmentManager fragmentManager = getFragmentManager();
                FragmentTransaction
             =fragmentTransaction=fragmentManager.beginTransaction();    

                ToDoFragment fragment = new ToDoFragment();
                fragmentTransaction.add(R.id.mainLL, fragment);
                fragmentTransaction.commit();
            }
        });





    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return true;
    }


    }

My main activity xml is

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


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="frag"
        android:id="@+id/fragButton"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:onClick="fragButtonClick"
        android:layout_gravity="center_horizontal" />




</LinearLayout>

Fragment.java

package com.example.mike.todolist;

import android.app.AlertDialog;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

import com.example.mike.todolist.db.Contract;
import com.example.mike.todolist.db.DBHelper;

/**
 * Created by mike on 6/10/15.
 */
public class ToDoFragment extends ListFragment {
    public ListAdapter listAdapter;
    public DBHelper helper;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                      Bundle savedInstanceState) {
        final View view=inflater.inflate(R.layout.fragmentlayout, container, false);


        // Inflate the layout for this fragment
        update();

        Button doneButton = (Button)view.findViewById(R.id.doneButton);
        doneButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                View v = (View) view.getParent();
                TextView taskTextView = (TextView) v.findViewById(R.id.taskTextView);
                String task = taskTextView.getText().toString();


                String sql = String.format("DELETE FROM %s WHERE %s = '%s'",
                        Contract.TABLE_NAME,
                        Contract.Columns.TASK,
                        task);


                helper = new DBHelper(getActivity());
                SQLiteDatabase sqlDB = helper.getWritableDatabase();
                sqlDB.execSQL(sql);
                update();
            }
        });

        Button addButton = (Button)view.findViewById(R.id.AddButton);
        addButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                switch (R.id.add_task) {
                    case R.id.add_task:
                        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                        builder.setTitle("Add a task");
                        builder.setMessage("What would you like to do?");
                        final EditText input = new EditText(getActivity());
                        builder.setView(input);
                        builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                String task = input.getText().toString();

                                helper = new DBHelper(getActivity());
                                SQLiteDatabase db = helper.getWritableDatabase();
                                ContentValues cv = new ContentValues();

                                cv.clear();
                                cv.put(Contract.Columns.TASK, task);

                                db.insertWithOnConflict(Contract.TABLE_NAME, null, cv, SQLiteDatabase.CONFLICT_IGNORE);
                                update();
                            }
                        });

                        builder.setNegativeButton("Cancel", null);

                        builder.create().show();


                }



            }
        });

        return view;


    }
    private void update() {
        helper = new DBHelper(getActivity());
        SQLiteDatabase sqlDB = helper.getReadableDatabase();
        Cursor cursor = sqlDB.query(Contract.TABLE_NAME,
                new String[]{Contract.Columns._ID, Contract.Columns.TASK},
                null, null, null, null, null);

        listAdapter = new SimpleCursorAdapter(
                getActivity(),
                R.layout.task_view,
                cursor,
                new String[]{Contract.Columns.TASK},
                new int[]{R.id.taskTextView},
                0
        );

        this.setListAdapter(listAdapter);
    }
}

and this is my fragmentlayout

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

    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@android:id/list"
        android:layout_weight="1"
        android:layout_margin="5dp"
        android:background="@color/grey"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Add Task"
        android:id="@+id/AddButton"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:onClick="AddButtonClick"
        android:layout_gravity="center_horizontal" />

</LinearLayout>

taskview

<?xml version="1.0" encoding="utf-8"?>

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

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/taskTextView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:textSize="20dp"
        android:textColor="@color/black"
        android:typeface="sans"
        android:layout_toLeftOf="@+id/doneButton"
        android:layout_alignBottom="@+id/doneButton"
        android:gravity="center_vertical"
        android:textStyle="bold"

        android:layout_alignTop="@+id/doneButton" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Done"
        android:id="@+id/doneButton"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:onClick="DoneButtonClick"
        />


</RelativeLayout>

According to android developers official website ( HERE )

ListActivity has a default layout that consists of a single, full-screen list in the center of the screen. However, if you desire, you can customize the screen layout by setting your own view layout with setContentView() in onCreate(). To do this, your own view MUST contain a ListView object with the id "@android:id/list" (or list if it's in code)

for example:

<?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"
         android:paddingLeft="8dp"
         android:paddingRight="8dp">

     <ListView android:id="@android:id/list"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:background="#00FF00"
               android:layout_weight="1"
               android:drawSelectorOnTop="false"/>

     <TextView android:id="@android:id/empty"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:background="#FF0000"
               android:text="No data"/>
 </LinearLayout>

So either add a listview to your list activity xml or if you don't need a list view in your activity then simply use FragmentActivity to hold fragments.There is no point in using ListActivity unless it holds a ListView.

use Activity or FragmentActivity instead of ListActivity

if you want to use ListActivity see here once. you can use ListActivity without setting content view (setContentView()). you can directly setAdapter. or else use your own layout having one ListView with id as "@android:id/list"

EDIT :

 public void onClick(View arg0) {
                TextView taskTextView = (TextView) view.findViewById(R.id.taskTextView);//directly use 'view' if 'R.id.taskTextView'it present in 'view'

                String task = taskTextView.getText().toString();

                String sql = String.format("DELETE FROM %s WHERE %s = '%s'",
                        Contract.TABLE_NAME,
                        Contract.Columns.TASK,
                        task);


                helper = new DBHelper(getActivity());
                SQLiteDatabase sqlDB = helper.getWritableDatabase();
                sqlDB.execSQL(sql);
                update();
            }

Add an list view to your xml with id android.R.id.list

 <ListView
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

add this xml to your layout

Your class is extending to a ListActivity which requires the ListView element in the xml. Your purpose be best served by extending your MainActivity class to Activity and fragments (if any) to Fragments class....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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