0

我是这样制作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;
}

}
4

1 回答 1

2

尝试在你的课堂上使用

而不是这个:

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

用这个:

fragmentPagerAdapterActosYCultos = new ConstructorFragmentos(getChildFragmentManager(), Constantes.ACTOS_Y_CULTOS, titulosTabs);
于 2013-08-31T20:27:37.280 回答