简体   繁体   English

在ViewPager中使用片段

[英]Using a fragment in ViewPager

I'm new to Android, this is my first project, I've spent a while trying to solve this now and have hit a bit of a dead end. 我是Android的新手,这是我的第一个项目,我花了一段时间尝试解决这个问题,但遇到了一些麻烦。 I'm wanting to open a fragment using ViewPager, and then access the fragment from the Activity it was opened from. 我想使用ViewPager打开一个片段,然后从打开它的Activity中访问该片段。 I have tried creating the fragment in the Activity rather than the ViewPager but that throws up a different error. 我尝试在Activity中创建片段,而不是在ViewPager中创建片段,但这引发了另一个错误。

public class TorchActivity extends SherlockFragmentActivity {

private static TorchFragment torchFrag;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
}   

public static class ViewPagerAdapter extends FragmentPagerAdapter {

    public ViewPagerAdapter(FragmentManager mgr) {
        super(mgr);
    }

    @Override
    public int getCount() {
        return (2);
    }

    @Override
    public Fragment getItem(int position) {
        if(position == 0){
            torchFrag = new TorchFragment();
            return torchFrag;
        }else{
            ColourPickerFragment colourPickerFrag = new ColourPickerFragment();
            return colourPickerFrag;
        }
    }
}
}

main.xml: main.xml中:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>

When I come to access the fragment later on in the same Activity I get a NullPointerException. 稍后当我在同一Activity中访问该片段时,我得到一个NullPointerException。

@Override
public void lightSensorCheck(boolean isThereALightSensor) {
    torchFrag.setIsThereALightSensor(isThereALightSensor);
}

In the fragment: 在片段中:

public void setIsThereALightSensor(boolean isThereALightSensor) {
    this.isThereALightSensor = isThereALightSensor;
}

It works fine if I take the ViewPager code out and run it, any help is appreciated. 如果我取出ViewPager代码并运行它,它将很好地工作,感谢您的帮助。

    02-17 16:01:30.132: E/AndroidRuntime(32006): FATAL EXCEPTION: main
02-17 16:01:30.132: E/AndroidRuntime(32006): java.lang.RuntimeException: Unable to start activity ComponentInfo{uk.co.bimrose.android.survivaltorch/uk.co.bimrose.android.survivaltorch.TorchActivity}: java.lang.NullPointerException
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2517)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2574)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.access$600(ActivityThread.java:162)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1413)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.os.Looper.loop(Looper.java:158)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.main(ActivityThread.java:5789)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at java.lang.reflect.Method.invokeNative(Native Method)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at java.lang.reflect.Method.invoke(Method.java:525)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:843)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at dalvik.system.NativeStart.main(Native Method)
02-17 16:01:30.132: E/AndroidRuntime(32006): Caused by: java.lang.NullPointerException
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.TorchActivity.lightSensorCheck(TorchActivity.java:199)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.updateLightSensorStatus(LightFragment.java:180)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.sensorCheck(LightFragment.java:134)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.onAttach(LightFragment.java:65)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:883)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:556)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.TorchActivity.onStart(TorchActivity.java:109)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1239)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.Activity.performStart(Activity.java:5205)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2490)
02-17 16:01:30.132: E/AndroidRuntime(32006):    ... 11 more

Here is the code for the fragment: 以下是该片段的代码:

public class TorchFragment extends SherlockFragment implements OnClickListener {

private Button buttonOn;
private Button buttonSos;
private Button buttonOff;

private TextView luxStatic;
private TextView luxMessage;
private TextView timerStatic;
private TextView timerMessage;
private TextView batteryStatic;
private TextView batteryMessage;
private TextView shutdownMessage;
private TextView shutdownMessageStatic;
private TextView timesUsed;

private ImageView img;
private TextView heading;

private SharedPreferences prefs;
private int lightSensitivity;
private boolean timerOn;
private int batteryPct;

private boolean isThereALightSensor;

public static int serviceCount;

private AlertResetListener alertResetListener;
private ServiceListener sListener;
private SetDataListener sDListener;
private ClearShutdownMessageListener cSMListener;
private ColourSchemeListener cSListener;

private int[] colourScheme = new int[4];
private LinearLayout dataCompassLayout;

int x = 0;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // Makes sure that the container activity has implemented the callback interface
    try {
        alertResetListener = (AlertResetListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement AlertReset");
    }

    // start / stop service
    try {
        sListener = (ServiceListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ServiceListener");
    }

    // Clear the dataFragment
    try {
        sDListener = (SetDataListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement SetDataListener");
    }

    // Clear the dataFragment shutdown message
    try {
        cSMListener = (ClearShutdownMessageListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ClearShutdownMessageListener");
    }

    // Get the colourscheme
    try {
        cSListener = (ColourSchemeListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ColourSchemeListener");
    }

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    View result = inflater.inflate(R.layout.torchfrag, parent, false);

    buttonOn = (Button) result.findViewById(R.id.button_on);
    buttonSos = (Button) result.findViewById(R.id.button_sos);
    buttonOff = (Button) result.findViewById(R.id.button_off);

    buttonOn.setText("ON");
    buttonOff.setText("OFF");
    buttonSos.setText("SOS");

    luxStatic = (TextView) result.findViewById(R.id.luxstatic);
    luxMessage = (TextView) result.findViewById(R.id.luxmessage);
    timerStatic = (TextView) result.findViewById(R.id.timerstatic);
    timerMessage = (TextView) result.findViewById(R.id.timermessage);
    batteryStatic = (TextView) result.findViewById(R.id.batterystatic);
    batteryMessage = (TextView) result.findViewById(R.id.batterymessage);
    shutdownMessage = (TextView) result.findViewById(R.id.shutdownmessage);
    shutdownMessageStatic = (TextView) result.findViewById(R.id.shutdownmessagestatic);
    timesUsed = (TextView) result.findViewById(R.id.timesused);

    timesUsed.setText(Integer.toString(TorchActivity.timesUsed));

    //Compass
    img = (ImageView) result.findViewById(R.id.compass);
    heading = (TextView) result.findViewById(R.id.heading);
    dataCompassLayout = (LinearLayout) result.findViewById(R.id.datacompasslayout);

    setColourScheme();

    buttonOn.setOnClickListener(this);
    buttonSos.setOnClickListener(this);
    buttonOff.setOnClickListener(this);

    return (result);
}

public void onResume() {
    setColourScheme();
    clearShutdownMessage();
    getPreferences();
    clearText();
    setStaticMessage();
    super.onResume();
}

@Override
public void onClick(View view) {
    alertResetListener.alertReset();
    TorchActivity.keepRunning = false;
    cSMListener.clearShutdownMessage();
    switch (view.getId()) {
    case R.id.button_on:
        serviceCount++;
        sListener.startService("on");
        break;
    case R.id.button_sos:
        serviceCount++;
        sListener.startService("sosPreset");
        break;
    case R.id.button_off:
        sListener.reset();
        sDListener.setData();
        break;
    default:
        throw new RuntimeException("Unknown button ID");
    }
}

private void setColourScheme(){
    //Calls the method from the activity which gets the colour scheme from the ColourSchemeFragment
    colourScheme = cSListener.getColourScheme();
    buttonOn.setBackgroundColor(getResources().getColor(colourScheme[0]));
    buttonOff.setBackgroundColor(getResources().getColor(colourScheme[1]));
    buttonSos.setBackgroundColor(getResources().getColor(colourScheme[2]));
    dataCompassLayout.setBackgroundColor(getResources().getColor(colourScheme[3]));
}

public void setSosTextColour(String s){
    int sosColour = 0;
    if(s.equals("white")){
        sosColour = R.color.button_text_sos;
    }else{
        sosColour = R.color.button_text_onoff;
    }
    try {
        XmlResourceParser parser = getResources().getXml(sosColour);
        ColorStateList colors = ColorStateList.createFromXml(getResources(), parser);
        buttonSos.setTextColor(colors);
    } catch (Exception e) {
        // handle exceptions
    }
}

// Called from TorchActivity whenever some new data is sent from one of the sensors
public void setMessage(int msg, String from) {
    if (from.equals("light")) {
        luxMessage.setText("Current LUX: " + Integer.toString(msg) + "\n");
    } else if (from.equals("timer")) {
        timerMessage.setText("Turns off in " + Integer.toString(msg) + " minutes\n");
    } else if (from.equals("battery")) {
        // Stops it updating battery % when the torch isn't on
        if (TorchActivity.keepRunning) {
            batteryMessage.setText("Current battery level: " + Integer.toString(msg) + "\n");
            //toast("********");
        }
    }
}

public void setStaticMessage() {
    if (lightSensitivity < 1000) {
        luxStatic.setText("Turns off at " + Integer.toString(lightSensitivity) + " LUX");
    }
    if (timerOn) {
        timerStatic.setText("Timer: ON");
    } else {
        timerStatic.setText("Timer: OFF");
    }
    if (batteryPct > 0) {
        batteryStatic.setText("Turns off at " + Integer.toString(batteryPct) + "% battery");
    }
    shutdownMessageStatic.setText("Torch stopped by: ");
}

public void clearText() {
    luxMessage.setText("\n");
    luxStatic.setText("Light Monitor: OFF");
    // only lets it clear the timer if the torch is off, && it's not the first time through. On the first time
    // through it was getting cleared when it shouldn't have been.
    if (!TorchActivity.keepRunning && !TorchActivity.autoOn) {
        timerMessage.setText("\n");
    }
    timerStatic.setText("\nTimer: OFF");
    batteryMessage.setText("\n");
    batteryStatic.setText("Battery monitor: OFF");
}

public void updateCompass(String s, RotateAnimation rA){
    img.startAnimation(rA);
    heading.setText(s);
}

public void setImageWhite(){
    img.setImageResource(R.drawable.compass_white);
}

public void setImageBlack(){
    img.setImageResource(R.drawable.compass);
}

private void getPreferences() {
    prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
    lightSensitivity = Integer.valueOf(prefs.getString("lightsensitivity", "1000000"));
    timerOn = prefs.getBoolean("timeron", false);
    batteryPct = Integer.valueOf(prefs.getString("batterypct", "50"));
}

// From TorchActivity
public void setShutdownMessage(String s) {
    shutdownMessage.setText("The " + s);
}

public void clearShutdownMessage() {
    shutdownMessage.setText("");
}

public void setIsThereALightSensor(boolean isThereALightSensor) {
    this.isThereALightSensor = isThereALightSensor;
}

public boolean getIsThereALightSensor() {
    return isThereALightSensor;
}

// Container Activity must implement this interface
public interface AlertResetListener {
    public void alertReset();
}

// Container Activity must implement this interface
public interface ServiceListener {
    public void startService(String s);

    // Resets the service and the timer
    public void reset();
}

// Container Activity must implement this interface
public interface SetDataListener {
    public void setData();
}

public interface ClearShutdownMessageListener {
    public void clearShutdownMessage();
}

public interface ColourSchemeListener {
    public int[] getColourScheme();
}

}

Looks like you are calling setIsThereALightSensor before the fragment is attached. 看起来您在附加片段之前正在调用setIsThereALightSensor

This is confirmed from your comment 这已从您的评论中确认

Quoting 引用

I solved the issue by starting the fragments in the onAttach in the TorchFragment (via the hosting activity) so it was up and running when it's methods were called 我通过在onAttach中的TorchFragment启动fragments (通过托管活动)解决了这个问题,因此在调用方法时它可以启动并运行

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

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