1

Je suis nouveau sur Android et j'essaie d'écrire une application Dummy simple pour apprendre quelque chose sur la création de propres classes View et ainsi de suite. Pourquoi je fais ça? Je voulais avoir une interface utilisateur qui se compose de plusieurs pages qui peuvent être parcourues en appuyant sur les boutons de la barre d'action. Je voulais maintenant ajouter la fonctionnalité de navigation via les gestes tactiles. J'ai ensuite fait face au problème que j'essayais de résoudre avec cette application fictive, qui fait la même chose que mon application originale, un peu plus simple.L'activité est en train d'être détruite en remplaçant Fragment

Le (ancien) problème: Les fragments ont un ScrollView d'un côté, qui mange le geste touche, lorsque vous cliquez dessus. Je lis à ce sujet et je devais créer mes propres FrameLayout et @Override les méthodes onInterceptTouchEvent et onTouchEvent. J'utilise maintenant ce nouveau FrameLayout comme mon conteneur de fragments. Pourtant, il ne fonctionne toujours pas correctement lorsque je teste l'application avec un ScrollView dans le FragmentLayout au lieu d'un LinearLayout (comme dans cet exemple de code). Mais à ce stade, ce n'est pas mon plus gros problème, je pense que je n'aurai qu'à travailler un peu sur les deux méthodes pour les faire fonctionner comme je veux.

A ce stade mon application se bloque lorsque les fragments sont échangés via des gestes tactiles ... Les boutons fonctionnent toujours.

Je reçois cette erreur (LogCat):

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) 

Ceci est mon MainActivity:

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(); 
    } 
} 

Ceci est mon 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; 
} 
} 

C'est le XML pour la vue simple:

<?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> 

Et voici ma classe 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); 
    } 
} 

classe 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"/> 

J'espère que quelqu'un peut aider, et que mon problème la description n'est pas trop confuse, et mon problème pas trop bête ...; s

Merci d'avance!

Répondre

0

Votre problème se produit ici dans votre MotionEventHandler

public class MotionEventHandler { 

    static final int MIN_X_DISTANCE = 150; 
    public float x1 = 0; 
    public float x2 = 0; 
    public float deltaX = 0; 

    // -- Right here -- 
    MainActivity myBoss = new MainActivity(); 

    // The rest of your code 
} 

L'erreur que vous obtenez est légèrement trompeur car ce n'est pas que votre MainActivity a été détruite. Ce problème est que celui que vous utilisez n'est pas celui qui est visible à l'écran. Dans presque tous les cas, vous ne voulez jamais instancier un Activity en appelant son constructeur.


Heureusement, la solution est relativement simple. Votre MotionEventHandler devrait avoir un constructeur qui prend dans un MainActivity comme ce qui suit:

public MotionEventHandler(MainActivity mainAct) { 
    myBoss = mainAct; 
} 

Et dans votre TouchInterceptingLayout vous devez instancier le gestionnaire à l'intérieur des constructeurs.

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 
} 
+0

Vous, monsieur, l'avez fait! :) Merci beaucoup! – walkslowly

Questions connexes