0

我做了這樣的應用:DrawerLayout + ViewPager緩存時

我試圖實現與ViewPager一個DrawerLayout。從DrawerLayout中選擇一個項目,輸入方法getItem(),並根據選擇的位置調用片段或其他。

在這個片段中,ViewPager被創建和構建。

在我的情況下,ViewPager包含三個碎片。

前三個Fargments構建沒有問題,並正確顯示。我想所有的東西都被緩存起來以提高性能。

現在我的評論我的問題:

當我在DrawerLayout選擇相同的項目,從另一個項目或通過單擊我同樣的事情,未來的問題就來了。

顯然,正如之前創建的碎片一樣,存儲在緩存中,現在不會進入構造函數。

的logcat中給了我以下錯誤:

FATAL EXCEPTION: main 
java.lang.NullPointerException 
at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:819) 
at android.support.v4.app.FragmentStatePagerAdapter.setPrimaryItem(FragmentStatePagerAdapter.java:152) 
at android.support.v4.view.ViewPager.populate(ViewPager.java:1066) 
at android.support.v4.view.ViewPager.populate(ViewPager.java:914) 
at android.support.v4.view.ViewPager$3.run(ViewPager.java:244) 
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) 
at android.view.Choreographer.doCallbacks(Choreographer.java:562) 
at android.view.Choreographer.doFrame(Choreographer.java:531) 
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) 
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:5103) 
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:737) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
at dalvik.system.NativeStart.main(Native Method) 

爲什麼這個問題呢?我如何找到解決方案?

我的代碼:

MainActivity.java

package com.android.projects.elprogramademano; 

import android.content.res.Configuration; 
import android.graphics.Color; 
import android.graphics.drawable.ColorDrawable; 
import android.graphics.drawable.Drawable; 
import android.graphics.drawable.LayerDrawable; 
import android.graphics.drawable.TransitionDrawable; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Handler; 
import android.support.v4.app.ActionBarDrawerToggle; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.view.GravityCompat; 
import android.support.v4.widget.DrawerLayout; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ListView; 

/** 
* Clase MainActivity (mainActivity.xml). 
*/ 
public class MainActivity extends FragmentActivity { 

// Declarar variables 
private DrawerLayout drawerLayout; 
private ListView listViewSecciones; 
private ActionBarDrawerToggle actionBarDrawerToggle; 
private ConstructorListaSecciones listaSecciones; 

private CharSequence tituloCajon; 
private CharSequence titulo; 
private String[] titulosSecciones; 
private int[] iconosSecciones; 
private Drawable oldBackground = null; 
private int colorFondoActionBar; 
private final Handler handler = new Handler(); 

private FragmentoActosYCultos fragmentoActosYCultos = new FragmentoActosYCultos(); 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // Establecer el titulo de la barra de acciones 
    titulo = tituloCajon = getTitle(); 

    // Cambiar el color de la barra de acciones 
    colorFondoActionBar = Constantes.COLOR_FONDO_ACTIONBAR; 
    cambiarColorBarraAcciones(colorFondoActionBar); 

    // Preparar el cajón de navegación 
    prepararCajonNavegacion(); 

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

/** 
* Método que se encarga de preparar el cajón de navegación. 
*/ 
private void prepararCajonNavegacion() { 
    // Generar los títulos de los secciones del cajón de navegación 
    titulosSecciones = getResources().getStringArray(R.array.secciones); 

    // Generar los iconos de los secciones del cajón de navegación 
    // iconosSecciones = new int[] { R.drawable.collections_cloud, R.drawable.collections_cloud, R.drawable.collections_cloud }; 

    // Localizar DrawerLayout en activity_main.xml 
    drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 

    // Localizar ListView in activity_main.xml 
    listViewSecciones = (ListView) findViewById(R.id.left_drawer); 

    // Establecer una sombra personalizado que se superpone a la página principal cuando el cajón se abre 
    drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); 

    // Pasar resultados a ConstructorListaSecciones.class 
    listaSecciones = new ConstructorListaSecciones(this, titulosSecciones, iconosSecciones); 

    // Establecer los ConstructorListaSecciones al ListView 
    listViewSecciones.setAdapter(listaSecciones); 

    // Capturar cuando se hace click sobre un sección del cajón de navegación 
    listViewSecciones.setOnItemClickListener(new DrawerItemClickListener()); 

    // Habilitar el icono de la barra de acciones para que se comporte como una acción 
    getActionBar().setHomeButtonEnabled(true); 
    getActionBar().setDisplayHomeAsUpEnabled(true); 

    // Lazos ActionBarDrawerToggle junto a los de las interacciones apropiadas 
    // Entre el cajón deslizante y la barra de iconos App acción 
    actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) { 

     public void onDrawerClosed(View view) { 
      // Cuando el cajón de navegación se cierra 
      super.onDrawerClosed(view); 
      getActionBar().setTitle(titulo); 
     } 

     public void onDrawerOpened(View drawerView) { 
      // Cuando el cajón de navegación se abre 
      super.onDrawerOpened(drawerView); 
      getActionBar().setTitle(tituloCajon); 
     } 
    }; 

    // Establecer el ActionBarDrawerToggle al DrawerLayout 
    drawerLayout.setDrawerListener(actionBarDrawerToggle); 
} 

@Override 
public void setTitle(CharSequence title) { 
    titulo = title; 
    getActionBar().setTitle(titulo); 
} 

@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) { 

    if (item.getItemId() == android.R.id.home) { 

     if (drawerLayout.isDrawerOpen(listViewSecciones)) { 
      drawerLayout.closeDrawer(listViewSecciones); 
     } else { 
      drawerLayout.openDrawer(listViewSecciones); 
     } 
    } 

    return super.onOptionsItemSelected(item); 
} 

/** 
* Clase DrawerItemClickListener. 
*/ 
private class DrawerItemClickListener implements ListView.OnItemClickListener { 
    @Override 
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
     selectItem(position); 
    } 
} 

/** 
* Metodo encargado de recuperar el sección seleccionado del cajón de navegación. 
* @param position int 
*/ 
private void selectItem(int position) { 

    // Localizar la posición 
    switch (position) { 
    case 0: 
     // Establezco el icono de la sección 
     // getActionBar().setIcon(R.drawable.ic_launcher_actionbar); 
     getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragmentoActosYCultos).commit(); 
     break; 
    case 1: 
     // Establezco el icono de la sección 
     // getActionBar().setIcon(R.drawable.ic_launcher_actionbar); 
     getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragmentoActosYCultos).commit(); 
     break; 
    case 2: 
     // Establezco el icono de la sección 
     // getActionBar().setIcon(R.drawable.ic_launcher_actionbar); 
     getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragmentoActosYCultos).commit(); 
     break; 
    } 

    // Establecer como marcado 
    listViewSecciones.setItemChecked(position, true); 

    // Establecer el titulo del sección en la barra de acciones 
    setTitle(titulosSecciones[position]); 

    // Cierre el cajón 
    drawerLayout.closeDrawer(listViewSecciones); 
} 

@Override 
protected void onPostCreate(Bundle savedInstanceState) { 
    super.onPostCreate(savedInstanceState); 
    // Sincronizar el estado de alternancia después de producirse onRestoreInstanceState. 
    actionBarDrawerToggle.syncState(); 
} 

@Override 
public void onConfigurationChanged(Configuration newConfig) { 
    super.onConfigurationChanged(newConfig); 
    // Pasar cualquier cambio en la configuración de las palancas del cajón 
    actionBarDrawerToggle.onConfigurationChanged(newConfig); 
} 

/** 
* Método encargado de cambiar el color de la barra de acciones. 
* @param color int 
*/ 
private void cambiarColorBarraAcciones(int color) { 
    // Cambiamos de color el ActionBar solo si existe alguno disponible. 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 

     Drawable colorDrawable = new ColorDrawable(color); 
     Drawable bottomDrawable = getResources().getDrawable(R.drawable.actionbar_bottom); 
     LayerDrawable ld = new LayerDrawable(new Drawable[] { colorDrawable, bottomDrawable }); 

     if (oldBackground == null) { 

      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       ld.setCallback(drawableCallback); 
      } else { 
       getActionBar().setBackgroundDrawable(ld); 
      } 

     } else { 

      TransitionDrawable td = new TransitionDrawable(new Drawable[] { oldBackground, ld }); 

      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       td.setCallback(drawableCallback); 
      } else { 
       getActionBar().setBackgroundDrawable(td); 
      } 

      td.startTransition(200); 

     } 

     oldBackground = ld; 

     getActionBar().setDisplayShowTitleEnabled(false); 
     getActionBar().setDisplayShowTitleEnabled(true); 

    } 

    colorFondoActionBar = color; 
} 

/** 
* Método que se ejecuta al pulsar sobre un color del layout. 
* @param view View 
*/ 
public void onColorClicked(View view) { 
    // Recuperamos el color pasado por el Tag desde el componente del layout. 
    int color = Color.parseColor(view.getTag().toString()); 
    // Cambiamos el color de la barra de acciones al color recuperado. 
    cambiarColorBarraAcciones(color); 
} 

private Drawable.Callback drawableCallback = new Drawable.Callback() { 
    @Override 
    public void invalidateDrawable(Drawable who) { 
     getActionBar().setBackgroundDrawable(who); 
    } 

    @Override 
    public void scheduleDrawable(Drawable who, Runnable what, long when) { 
     handler.postAtTime(what, when); 
    } 

    @Override 
    public void unscheduleDrawable(Drawable who, Runnable what) { 
     handler.removeCallbacks(what); 
    } 
}; 

} 

FragmentoActosYCultos.java

package com.android.projects.elprogramademano; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.view.ViewPager; 
import android.util.TypedValue; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

import com.android.libraries.pagerslidingtabstrip.PagerSlidingTabStrip; 

/** 
* Clase FragmentoActosYCultos (actos_y_cultos.xml). 
*/ 
public class FragmentoActosYCultos extends Fragment { 

// Declarar variables 
private View viewActosYCultos; 
private ViewPager viewPagerActosYCultos; 
private PagerSlidingTabStrip pagerSlidingTabStripActosYCultos; 
private ConstructorFragmentos fragmentPagerAdapterActosYCultos; 
private String[] titulosTabs; 
private int colorFondoPagerSlidingTabStrip; 
private int colorIndicadorPagerSlidingTabStrip; 

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

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    // Localizar el layout 
    viewActosYCultos = inflater.inflate(R.layout.actos_y_cultos, container, false); 

    // Localizar ViewPager en actos_y_cultos.xml 
    viewPagerActosYCultos = (ViewPager) viewActosYCultos.findViewById(R.id.viewPagerActosYCultos); 

    // Localizar PagerSlidingTabStrip en actos_y_cultos.xml 
    pagerSlidingTabStripActosYCultos = (PagerSlidingTabStrip) viewActosYCultos.findViewById(R.id.pagerTabSlidingStripActosYCultos); 

    // Construir el ConstructorFragmentos 
    titulosTabs = getResources().getStringArray(R.array.dias); 
    fragmentPagerAdapterActosYCultos = new ConstructorFragmentos(getFragmentManager(), Constantes.ACTOS_Y_CULTOS, titulosTabs); 

    // Establecer el ConstructorFragmentos al ViewPager 
    viewPagerActosYCultos.setAdapter(fragmentPagerAdapterActosYCultos); 

    // Establecer los margenes al ViewPager 
    final int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics()); 
    viewPagerActosYCultos.setPageMargin(pageMargin); 

    // Establecer el ViewPager al PagerSlidingTabStrip 
    pagerSlidingTabStripActosYCultos.setViewPager(viewPagerActosYCultos); 

    // Establecer color al fondo del PagerSlidingTabStrip 
    colorFondoPagerSlidingTabStrip = Constantes.COLOR_FONDO_PAGER_SLIDING_TAB_STRIP; 
    pagerSlidingTabStripActosYCultos.setBackgroundColor(colorFondoPagerSlidingTabStrip); 

    // Establecer color al indicador del PagerSlidingTabStrip 
    colorIndicadorPagerSlidingTabStrip = Constantes.COLOR_FONDO_ACTIONBAR; 
    pagerSlidingTabStripActosYCultos.setIndicatorColor(colorIndicadorPagerSlidingTabStrip); 

    return viewActosYCultos; 
} 

} 

ConstructorFragmentos.java

package com.android.projects.elprogramademano; 

import java.util.Locale; 

import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.app.FragmentStatePagerAdapter; 
import android.view.ViewGroup; 

/** 
* Clase ConstructorFragmentos. 
*/ 
public class ConstructorFragmentos extends FragmentStatePagerAdapter { 

// Declarar variables 
private String activity; 
private String[] titulosTabs; 

/** 
* Constructor de la clase. 
* @param fm FragmentManager 
* @param act String 
* @param titulosTabs String[] 
*/ 
public ConstructorFragmentos(FragmentManager fm, String act, String[] titulosTabs) { 
    super(fm); 

    // Recuperamos los parámetros. 
    activity = act; 
    this.titulosTabs = titulosTabs; 
} 

/* 
* Método encargado de recuperar el titulo del Tab actual. 
*/ 
@Override 
public CharSequence getPageTitle(int position) { 
    Locale l = Locale.getDefault(); 
    return titulosTabs[position].toUpperCase(l); 
} 

/* 
* Método encargado de recuperar el total de Tabs. 
*/ 
@Override 
public int getCount() { 
    return titulosTabs.length; 
} 

/* 
* Método encargado de construir los fragmentos del layout actual. 
*/ 
@Override 
public Fragment getItem(int position) { 
    Fragment fragment = new Fragment(); 

    if (activity != null && !activity.isEmpty()) { 
     // Si la actividad no es nula ni está vacía. 
     if (activity.equals(Constantes.PROCESIONES)) { 
      // Si es PROCESIONES. 
      fragment = ConstructorFragmentosProcesiones.newInstance(position); 
     } else if (activity.equals(Constantes.ACTOS_Y_CULTOS)){ 
      // Si es ACTOSYCULTOS. 
      fragment = ConstructorFragmentosActosYCultos.newInstance(position); 
     } 
    } 

    return fragment; 
} 

@Override 
public void destroyItem(ViewGroup container, int position, Object object) { 
    super.destroyItem(container, position, object); 
} 

@Override 
public Object instantiateItem(ViewGroup arg0, int arg1) { 
    return super.instantiateItem(arg0, arg1); 
} 

@Override 
public int getItemPosition(Object object) { 
    return super.getItemPosition(object); 
} 

} 

ConstructorFragmentosActosYCultos.java

package com.android.projects.elprogramademano; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.util.TypedValue; 
import android.view.Gravity; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.FrameLayout; 
import android.widget.TextView; 
import android.widget.FrameLayout.LayoutParams; 
import android.widget.Toast; 

/** 
* Clase ConstructorFragmentosActosYCultos. 
*/ 
public class ConstructorFragmentosActosYCultos extends Fragment { 

// Declarar variables 
private static final String ARG_POSITION = "position"; 
private int position; 

/** 
* Constructor de la clase. 
* @param position int 
* @return ConstructorFragmentosActosYCultos 
*/ 
public static ConstructorFragmentosActosYCultos newInstance(int position) { 
    ConstructorFragmentosActosYCultos f = new ConstructorFragmentosActosYCultos(); 
    Bundle b = new Bundle(); 
    b.putInt(ARG_POSITION, position); 
    f.setArguments(b); 
    return f; 
} 

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

    position = getArguments().getInt(ARG_POSITION); 
} 

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

    LayoutParams params = new LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, android.view.ViewGroup.LayoutParams.MATCH_PARENT); 

    FrameLayout fl = new FrameLayout(getActivity()); 
    fl.setLayoutParams(params); 

    final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()); 

    TextView v = new TextView(getActivity()); 
    params.setMargins(margin, margin, margin, margin); 
    v.setLayoutParams(params); 
    v.setGravity(Gravity.CENTER); 
    v.setBackgroundResource(R.drawable.background_card); 
    v.setText("ACTOS Y CULTOS " + (position + 1)); 

    fl.addView(v); 
    fl.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      Toast.makeText(getActivity(), "PULSADO ACTOS Y CULTOS " + (position + 1), Toast.LENGTH_SHORT).show(); 

     } 
    }); 

    return fl; 
} 

} 
+0

你的問題是視圖尋呼機的片段正在消失??? – 2013-08-30 13:21:26

+0

@KingOmar是的,當我第二次訪問碎片消失,我得到錯誤 – user2713868

回答

2

嘗試使用在你的類

取而代之的是:

fragmentPagerAdapterActosYCultos = new ConstructorFragmentos(getFragmentManager(), Constantes.ACTOS_Y_CULTOS, titulosTabs); 

使用:

fragmentPagerAdapterActosYCultos = new ConstructorFragmentos(getChildFragmentManager(), Constantes.ACTOS_Y_CULTOS, titulosTabs); 
+0

@ KingOmar感謝您的幫助。它的工作,但現在我發現另一個問題。 當我輸入的第二時間成DrawerLayout選項引發錯誤消息: 'java.lang.IllegalStateException:在android.support.v4.app.FragmentManagerImpl.moveToState沒有活動 (FragmentManager.java:1091)' – user2713868

+0

可以你過去了整個logcat? –

+0

'致命異常:主要 java.lang.IllegalStateException:在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1091)無活動 在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager .java:1086) at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1877) at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1492) at android.support .v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)'@KingOmar – user2713868