Android 正在替换碎片时销毁活动

Android 正在替换碎片时销毁活动,android,android-layout,android-fragments,android-framelayout,fragmentmanager,Android,Android Layout,Android Fragments,Android Framelayout,Fragmentmanager,我是Android新手,正在尝试编写一个简单的虚拟应用程序,学习如何创建自己的视图类等等。 我为什么要这样做?我希望有一个UI,它由几个页面组成,可以通过按操作栏上的按钮来导航。我现在想添加通过触摸手势导航的功能。然后我遇到了我试图用这个虚拟应用程序解决的问题,它和我原来的应用程序一样,只是简单了一点 前一个问题: 这些碎片的一侧确实有一个滚动视图,当你点击它们时,它会吃掉触摸手势 我读了这篇文章,发现我必须创建自己的FrameLayout并@Override onInterceptTouchE

我是Android新手,正在尝试编写一个简单的虚拟应用程序,学习如何创建自己的视图类等等。 我为什么要这样做?我希望有一个UI,它由几个页面组成,可以通过按操作栏上的按钮来导航。我现在想添加通过触摸手势导航的功能。然后我遇到了我试图用这个虚拟应用程序解决的问题,它和我原来的应用程序一样,只是简单了一点

前一个问题: 这些碎片的一侧确实有一个滚动视图,当你点击它们时,它会吃掉触摸手势

我读了这篇文章,发现我必须创建自己的FrameLayout并@Override onInterceptTouchEvent和onTouchEvent方法。我现在使用这个新的FrameLayout作为片段容器。然而,当我在FragmentLayout中使用ScrollView而不是这个代码示例中的LinearLayouts测试应用程序时,它仍然不能正常工作。但在这一点上,这不是我最大的问题,我想我只需要在这两种方法上做一点工作,就能让它们按照我的意愿工作

此时,当碎片通过触摸手势交换时,我的应用程序崩溃。。。按钮仍在工作

我收到了这个错误日志:

06-18 14:34:03.295: W/dalvikvm(2983): threadid=1: thread exiting with uncaught exception (group=0x409f51f8)
06-18 14:34:03.305: E/AndroidRuntime(2983): FATAL EXCEPTION: main
06-18 14:34:03.305: E/AndroidRuntime(2983): java.lang.IllegalStateException: Activity has been destroyed
06-18 14:34:03.305: E/AndroidRuntime(2983):     at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1280)
06-18 14:34:03.305: E/AndroidRuntime(2983):     at android.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
06-18 14:34:03.305: E/AndroidRuntime(2983):     at android.app.BackStackRecord.commit(BackStackRecord.java:525)
06-18 14:34:03.305: E/AndroidRuntime(2983):     at com.example.trysomething.MainActivity.switchFragment(MainActivity.java:97)
06-18 14:34:03.305: E/AndroidRuntime(2983):     at com.example.trysomething.MainActivity.navForward(MainActivity.java:74)
这是我的主要活动:

public class MainActivity extends Activity {

    int pos;

    TouchInterceptingLayout mtil;

    CharSequence mTitle;
    String[] mTitles;

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

        mtil = (TouchInterceptingLayout) findViewById(R.id.fragment_container);

        pos = 0;
        mTitle = getTitle();
        mTitles = getResources().getStringArray(R.array.dummy_seiten);

        if(savedInstanceState == null){
            switchFragment(0);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){

        switch(item.getItemId()){
        case R.id.action_nav_back:
            navBackwards();
            break;
        case R.id.action_nav_forward:
            navForward();
            break;
        }

        return super.onOptionsItemSelected(item);
    }

    public void setTitle(CharSequence title){
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

    public void navForward(){
        if(pos == 2){
            pos = 0;
            switchFragment(pos);
        } else {
            pos += 1;
            switchFragment(pos);
        }
    }

    public void navBackwards(){
        if(pos == 0){
            pos = 2;
            switchFragment(pos);
        } else {
            pos -= 1;
            switchFragment(pos);
        }
    }

    public void switchFragment(int position){
        Fragment newFrag;
        Bundle args = new Bundle();
        args.putInt(DummyFragmentSimpleView.ARG_POSITION, position);
        newFrag = new DummyFragmentSimpleView();
        newFrag.setArguments(args);
        android.app.FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.fragment_container, newFrag);
        ft.commit();
    }
}
这是我的DummyFragmentSimpleView Java:

public class DummyFragmentSimpleView extends Fragment {

public static String ARG_POSITION = "position";

Bundle args;

String[] dummyStringArray;
String[] nonsenseArray;

LayoutParams params;

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    dummyStringArray = getResources().getStringArray(R.array.dummy_array);
    nonsenseArray = getResources().getStringArray(R.array.nonsense_array);
    params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    args = getArguments();
}

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

    View mySimpleFrag = inflater.inflate(R.layout.fragment_notscrolling, container, false);

    ImageView image = (ImageView) mySimpleFrag.findViewById(R.id.image_container);
    String bild = getResources().getStringArray(R.array.dummy_seiten)[args.getInt(ARG_POSITION)];
    int bildId = getResources().getIdentifier(bild.toLowerCase(Locale.getDefault()), "drawable", getActivity().getPackageName());
    ((ImageView) image).setImageResource(bildId);

    LinearLayout dummyLayout = (LinearLayout) mySimpleFrag.findViewById(R.id.content_container);

    TextView t = (TextView) mySimpleFrag.findViewById(R.id.nonsense_text);
    t.setText(nonsenseArray[args.getInt(ARG_POSITION)]);

    for(int i = 0; i < dummyStringArray.length; i++){
        TextView text = new TextView(getActivity());
        text.setText(dummyStringArray[i]);
        text.setId(i);
        text.setLayoutParams(params);
        text.setTextSize(20);
        ((LinearLayout) dummyLayout).addView(text);         
    }

    getActivity().setTitle(bild);

    return mySimpleFrag;
}
}
这是简单视图的XML:

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

    <LinearLayout 
        android:id="@+id/left_panel"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#C00000"
        android:gravity="center">

        <ImageView
            android:id="@+id/image_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>



        <LinearLayout
            android:id="@+id/right_panel"
            android:layout_weight="2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView 
                android:id="@+id/nonsense_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="30sp"
                android:textStyle="bold"/>

            <LinearLayout 
                android:id="@+id/content_container"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>

        </LinearLayout>



</LinearLayout>
这是我的TouchInterceptingLayout课程:

public class TouchInterceptingLayout extends FrameLayout{

    boolean mIsNavigating = false;

    MotionEventHandler handler = new MotionEventHandler();

    public TouchInterceptingLayout(Context context) {
        super(context);
    }

    public TouchInterceptingLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TouchInterceptingLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        for(int i = 0; i < getChildCount(); i++){
            getChildAt(i).layout(left, top, right, bottom);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event){

        float x1 = 0;
        float x2 = 0;

        final int action = event.getAction();

        if(action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP){
            mIsNavigating = false;
            return false;
        }

        switch (action){
        case MotionEvent.ACTION_DOWN:
            x1 = event.getX();
            break;
        case MotionEvent.ACTION_MOVE:
            return false;
        case MotionEvent.ACTION_UP:
            x2 = event.getX();
            if(Math.abs(x2 - x1) > 150){
                mIsNavigating = true;
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            handler.setXOne(event.getX());
            return true;

        case MotionEvent.ACTION_UP:
            handler.setXTwo(event.getX());
            handler.setDelta();
            handler.performAction();
            break;
        }
        return super.onTouchEvent(event);
    }
}
MotionEventHandler类:

public class MotionEventHandler {

    static final int MIN_X_DISTANCE = 150;
    public float x1 = 0;
    public float x2 = 0;
    public float deltaX = 0;
    MainActivity myBoss = new MainActivity();

    public MotionEventHandler(){
    }

    public void setXOne(float x){
        x1 = x;
    }

    public void setXTwo(float x){
        x2 = x;
    }

    public float getXOne(){
        return x1;
    }

    public float getXTwo(){
        return x2;
    }

    public void setDelta(){
        deltaX = x2 - x1;
    }

    public float getDelta(){
        return deltaX;
    }

    public boolean isPageBeingSwapped(){
        if (Math.abs(deltaX)<MIN_X_DISTANCE){
            return false;
        } else {
            return true;
        }
    }

    public void performAction(){
        if(isPageBeingSwapped()){
            if(deltaX < 0){
                myBoss.navBackwards();
            } else {
                myBoss.navForward();
            }
        }
    }
}
activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
    <com.example.trysomething.TouchInterceptingLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
我希望有人能帮忙,我的问题描述不要太混乱,我的问题也不要太愚蠢;


提前谢谢

您的问题就发生在MotionEventHandler中

您得到的错误有点误导,因为您的主要活动并没有被破坏。这个问题是你使用的不是屏幕上可见的。几乎在所有情况下,您都不希望通过调用活动的构造函数来实例化活动

幸运的是,解决这个问题相对容易。MotionEventHandler应该有一个构造函数,该构造函数接受MainActivity,如下所示:

public MotionEventHandler(MainActivity mainAct) {
    myBoss = mainAct;
}
在TouchInterceptingLayout中,您应该在构造函数中实例化处理程序

public class TouchInterceptingLayout extends FrameLayout{
    MotionEventHandler handler;

    public TouchInterceptingLayout(Context context) {
        super(context);
        if(context instanceof MainActivity) {
            handler =  = new MotionEventHandler((MainActivity) context)
        }
        else {
            // Not a valid context
        }
    }
    public TouchInterceptingLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TouchInterceptingLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if(context instanceof MainActivity) {
            handler =  = new MotionEventHandler((MainActivity) context)
        }
        else {
            // Not a valid context
        }
    }

    // The rest of your code
}

先生,是你让这一切发生的谢谢!
public class TouchInterceptingLayout extends FrameLayout{
    MotionEventHandler handler;

    public TouchInterceptingLayout(Context context) {
        super(context);
        if(context instanceof MainActivity) {
            handler =  = new MotionEventHandler((MainActivity) context)
        }
        else {
            // Not a valid context
        }
    }
    public TouchInterceptingLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TouchInterceptingLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        if(context instanceof MainActivity) {
            handler =  = new MotionEventHandler((MainActivity) context)
        }
        else {
            // Not a valid context
        }
    }

    // The rest of your code
}