0

私はこのようにアプリを作りました:

ViewPager で DrawerLayout を実装しようとしています。DrawerLayout からアイテムを選択すると、メソッドに入り、getItem()選択した位置に応じて Fragment または別のメソッドが呼び出されます。

この Fragment では、ViewPager が作成およびビルドされます。

私の場合、ViewPager には 3 つの Fragment が含まれています。

最初の 3 つの Fargments は問題なくビルドされ、正しく表示されます。パフォーマンスを向上させるためにすべてがキャッシュされていると思います。

今私は私の問題にコメントします:

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 に答える