2013-03-20 6 views
6

Questo è un problema di 2 parti. Quello che sto vedendo è un layout di 3 Fragment in cui il 3'rd Fragment (FragmentC) viene aggiunto dinamicamente quando l'utente tocca un pulsante trovato in un altro frammento. Quindi, dopo che è stato aggiunto, il 3 ° frammento ha un pulsante per massimizzarlo/ridurlo al minimo.Mostra/Nascondi frammenti e modifica l'attributo di visibilità a livello di programmazione

UPDATE: Scrool alla fine per SOLUZIONE



PROBLEMA 1:

sto cercando di cambiare l'attributo visibilità di un FrameLayout che funge da contenitore per il 3 ° frammento (R.id.fragment_C).

Quello che il codice dovrebbe fare è generare un altro frammento che, in origine, contiene un XML contenente android: visibility = "gone". Quindi, il frammento viene aggiunto quando si tocca un pulsante e si suppone che la visibilità cambi in VISIBILE.

So che questo è stato trattato prima, ma dopo 4 ore di provare a farlo funzionare ho deciso di chiedere cosa sto sbagliando.

PROBLEMA 2:

Dopo il frammento 3'rd viene generato ho un pulsante di minimizzare/massimizzare che dovrebbe nascondere i primi 2 Frammenti e permettere al frammento 3'rd per riempire lo schermo.

Il problema sono le viste dei primi 2 Frammenti non vengono rimossi quando si utilizza .setVisibility (View.GONE). Anche questo è stato trattato prima, ma non riesco a capire perché non funziona nel mio codice.

Il codice finora (scusate se è a verbose ma ho pensato che è meglio per includere tutti i dettagli per voi gente):

main_activity.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:paddingLeft="0dp" 
    android:paddingRight="0dp" 
    android:orientation="vertical" 
    > 

    <FrameLayout 
     android:id="@+id/fragment_A" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_alignParentTop="true" 
     android:layout_centerHorizontal="true" 
     android:background="#CCCCCC" 
     > 
    </FrameLayout> 

    <FrameLayout 
     android:id="@+id/fragment_B" 
     android:layout_width="fill_parent" 
     android:layout_height="300dp" 
     android:layout_below="@id/fragment_A" 
     android:layout_centerHorizontal="true" 
     android:layout_marginTop="15dp" 
     android:background="#B4B4B4" 
     > 
    </FrameLayout> 

    <FrameLayout 
     android:id="@+id/fragment_C" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_below="@id/fragment_B" 
     android:layout_centerHorizontal="true" 
     android:layout_marginTop="0dp" 
     android:background="#A3A3A3" 
     android:visibility="gone" 
     > 
    </FrameLayout> 

</RelativeLayout> 

terra/main_activity.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" 
    android:paddingLeft="0dp" 
    android:paddingRight="0dp" > 

    <LinearLayout 
     android:id="@+id/fragments_container" 
     android:layout_width="fill_parent" 
     android:layout_height="200dp" 
     android:baselineAligned="false" > 

     <FrameLayout 
      android:id="@+id/fragment_A" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:layout_weight="0.5" 
      android:background="#CCCCCC" > 
     </FrameLayout> 

     <FrameLayout 
      android:id="@id/fragment_B" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:layout_weight="0.5" 
      android:background="#B4B4B4" 
      > 
     </FrameLayout> 
    </LinearLayout> 

    <FrameLayout 
     android:id="@+id/fragment_C" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:layout_below="@id/fragment_container" 
     android:layout_centerHorizontal="true" 
     android:layout_marginTop="0dp" 
     android:background="#A3A3A3" 
     android:visibility="gone" > 
    </FrameLayout> 

</RelativeLayout> 

MainActivity.java

package com.example.android.fragments_proto.activity; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentTransaction; 

import com.example.android.fragments_proto.R; 
import com.example.android.fragments_proto.fragment.GMC_DateSelectionFragment; 
import com.example.android.fragments_proto.fragment.GMC_ProdUnitSelectionFragment; 

public class MainActivity extends FragmentActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.main_activity); 

     FragmentManager fm = getSupportFragmentManager(); 

     Fragment fragmentA = fm.findFragmentById(R.id.fragment_A); 

     Fragment fragmentB = fm.findFragmentById(R.id.fragment_B); 

     if (fragmentA == null) { 

      FragmentTransaction ft = fm.beginTransaction(); 
      ft.add(R.id.fragment_A, new FragmentA()); 
      ft.commit(); 
     } 

     if (fragmentB == null) { 

      FragmentTransaction ft = fm.beginTransaction(); 
      ft.add(R.id.fragment_B, new FragmentB()); 
      ft.commit(); 
     } 
    } 
} 

Ora i file XML e .java per il primo frammento.

fragment_A.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:gravity="center_horizontal" 
    > 

    <DatePicker 
     android:id="@+id/datePicker1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

FragmentA.java

package com.example.android.fragments_proto.fragment; 

import android.app.Activity; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 
import android.view.ViewGroup; 
import android.widget.DatePicker; 
import android.widget.Toast; 

import com.example.android.fragments_proto.R; 

public class FragmentA extends Fragment { 

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

     View view = inflater.inflate(R.layout.fragment_A, container, false); 

     DatePicker datePicker = (DatePicker) view.findViewById(R.id.datePicker1); 
     datePicker.setCalendarViewShown(true); 
     datePicker.setSpinnersShown(false);    

     datePicker.setOnTouchListener(new OnTouchListener() { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       Activity activity = getActivity(); 

        if (activity != null) { 

         Toast.makeText(activity, "You Touched ME!", Toast.LENGTH_SHORT).show(); 
        } 
      return false; 
      } 
     }); 

     return view; 
    } 
} 

Ora l'XML e file .java per il frammento che contiene il pulsante che, quando batté aggiunge il contenuto in R .id.fragment_C

framment_B.xml

<?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:layout_height="fill_parent" 
    > 

    <LinearLayout 
     android:orientation="horizontal" 
     android:layout_width="fill_parent" 
     android:layout_height="0dp" 
     android:layout_weight="0.1" 
     > 

     <ListView 
      android:id="@+id/listView1" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      > 
     </ListView> 

    </LinearLayout> 

    <LinearLayout 
     android:layout_width="fill_parent" 
     android:orientation="horizontal" 
     android:gravity="center" 
     android:layout_height="wrap_content"> 

      <Button 
       android:id="@+id/button" 
       android:text="@string/btn_fragment" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
      /> 

    </LinearLayout> 

</LinearLayout> 

FragmentB.java

package com.example.android.fragments_proto.fragment; 

import android.app.Activity; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentTransaction; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.ListView; 

import com.example.android.fragments_proto.R; 

public class FragmentB extends Fragment { 

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

     View view = inflater.inflate(R.layout.fragmentB, container, false); 

     ListView listView = (ListView) view.findViewById(R.id.listView1); 
     Button button = (Button) view.findViewById(R.id.button); 

     String[] machines = new String[] { "MachineId-001", "MachineId-002", "MachineId-003", "MachineId-004", "MachineId-005", "MachineId-006", "MachineId-007", "MachineId-008"}; 

     listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
     listView.setAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.select_dialog_multichoice, machines)); 
     final FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.fragment_C); 

     button.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       Activity activity = getActivity(); 

       if (activity != null) { 
        getFragmentManager().beginTransaction().replace(R.id.fragment_C, new FragmentC()).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).addToBackStack(null).commit(); 
        frameLayout.setVisibility(View.VISIBLE); 
       } 
      } 

     }); 

     return view; 
    } 

} 

L'XML e file .java per il frammento che dovrebbe essere aggiunto.

fragment_C.xml

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

    <LinearLayout 
     android:layout_width="fill_parent" 
     android:orientation="horizontal" 
     android:gravity="center" 
     android:layout_height="wrap_content"> 

    <Button 
     android:id="@+id/maximize_button" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="Maximize Me!" /> 

    </LinearLayout> 

    <TextView 
     android:id="@+id/text_view" 
     android:textIsSelectable="true" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:background="#FF33FF" 
     /> 

</LinearLayout> 

FragmentC.java

package com.example.android.fragments_proto.fragment; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentTransaction; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.Button; 
import android.widget.TextView; 

import com.example.android.fragments_proto.R; 

public class FragmentC extends Fragment { 

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

     View view = inflater.inflate(R.layout.fragment_C, container, false); 

     TextView textView = (TextView) view.findViewById(R.id.text_view); 

      final Fragment fragmentA = getFragmentManager().findFragmentById(R.id.fragment_A); 
      final Fragment fragmentB = getFragmentManager().findFragmentById(R.id.fragment_B); 

      button.setOnClickListener(new OnClickListener() { 
       public void onClick(View v) { 
        FragmentTransaction ft = getFragmentManager().beginTransaction(); 

        if (fragmentA.isVisible() && fragmentB.isVisible()) { 
         ft.hide(fragmentA); 
         ft.hide(fragmentB); 
         fragmentA.getView().setVisibility(View.GONE); 
         fragmentB.getView().setVisibility(View.GONE); 
         button.setText("Minimize Me!"); 
         ft.addToBackStack(null); 
        } else { 
         ft.show(fragmentA); 
         ft.show(fragmentB); 
         fragmentA.getView().setVisibility(View.VISIBLE); 
         fragmentB.getView().setVisibility(View.VISIBLE); 
         button.setText("Maximize Me!"); 
         ft.addToBackStack(null); 
        } 
        ft.commit(); 
       } 
      });  

     return view; 

    } 
} 




trovato il problema e una soluzione grazie alla Moesio

PROBLEMA:

Il mio errore è stato che stavo cercando di trovare una vista (in FragmentB.java) con

finale FrameLayout frameLayout = (FrameLayout) view.findViewById (R.id. fragment_C);

Questa riga restituiva null in modo tale che quando il codice raggiungeva il punto in cui doveva eseguire .setVisibility(), quindi l'app. restituirebbe nullPointerException.

Lo stesso è successo per FragmentC.java (quindi i miei 2 problemi erano correlati). Le viste non sono state rimosse perché il mio findViewById era nullo!


SOLUZIONE:

Basta cercare la tua vista con getActivity .findViewById (R.id.your_view);

+0

incollo il codice in un progetto locale e credo di aver trovato la causa 'null'. Ho modificato potrebbe rispondere. Leggere sotto. – Moesio

risposta

4

In FragmentB si sta cercando ottenere una vista che non è sul contentView

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

    View view = inflater.inflate(R.layout.fragment_b, container, false); 

    // this is in fragment_b layout 
    ListView listView = (ListView) view.findViewById(R.id.listView1); 
    Button button = (Button) view.findViewById(R.id.button); 

    /* ... */ 
    // **************************************** 
    // this is NOT in fragment_b layout, which causes null 
    // **************************************** 
    final FrameLayout frameLayout = (FrameLayout) view.findViewById(R.id.fragment_C); 

    /* ... */ 
} 

Prova:

final FrameLayout frameLayout = (FrameLayout) getActivity().getWindow().findViewById(R.id.fragment_C); 

Mentre R.id.fragment_C è gonfiato e impostato al MainActivity.

Inoltre, ho avuto lo stesso problema fino a quando utilizzare una bandiera in più

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
    final Fragment fragmentC = new FragmentC(); 
    fragmentTransaction.add(R.id.fragment_C, fragmentC); 
    fragmentTransaction.commit(); 
    menuIsOn = false; 

    final View fragmentCView = findViewById(R.id.fragment_C); 

    final Button btn = (Button) findViewById(R.id.btn); 
    btnPowers.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (!menuIsOn) { 
       fragmentCView.setVisibility(View.VISIBLE); 
      } else { 
       fragmentCView.setVisibility(View.INVISIBLE); 
      } 
      menuIsOn = !menuIsOn; 
     } 
    }); 
+0

Grazie per la risposta. Mi dispiace chiedere questo, ma non è chiaro. Devo aggiungere il 3 ° frammento su un clic del pulsante (nel mio esempio che funziona fintanto che non aggiungo l'attributo visibilità nell'XML). Il problema è che quando lo aggiungo e tocco il pulsante (vedi FragmentB.java) che dovrebbe aggiungere il mio frammento 3 °, il mio attributo visibilità genera una java.lang.NullPointerException e l'app si blocca. Come può la tua risposta risolvere questo? – sebster

+0

Quello che non capisco è perché il mio codice genera una NullPointerException. Se dai un'occhiata al mio esempio di FragmentB.java, io uso un codice abbastanza simile al tuo. Non riesco a capire dove sia la differenza e come potrebbe aiutare il mio FragmentB – sebster

+0

Che cos'è null? Dove succede? – Moesio

Problemi correlati