我是这样制作app的:
我正在尝试使用 ViewPager 实现 DrawerLayout。从 DrawerLayout 中选择一个项目,进入方法getItem()
并根据所选位置调用 Fragment 或另一个。
在这个 Fragment 中,创建并构建了 ViewPager。
在我的例子中,ViewPager 包含三个片段。
前三个片段构建没有问题并正确显示。我认为一切都被缓存以提高性能。
现在我评论我的问题:
当我在 DrawerLayout 中选择相同的项目、来自另一个项目或单击与我相同的项目时,问题就出现了。
显然,就像之前创建的 Fragments 一样,它存储在缓存中,现在不进入构造函数。
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;
}
}
构造函数Fragmentos.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);
}
}
构造函数FragmentosActosYCultos.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;
}
}