without viewpager pagetransformer not fragments example android user-interface android-layout android-fragments android-viewpager

pagetransformer - Android: ViewPager se bloquea entre las vistas



viewpager not fragments (5)

Tengo un ViewPager que se desliza entre fragmentos. Estoy usando un FragmentStatePagerAdapter para alimentar los Fragmentos al ViewPager. Si el usuario desliza a la izquierda a un ritmo normal, y luego lo hace muy rápidamente, puede hacer que el ViewPager se encuentre en un estado extraño en el que muestre múltiples Fragmentos.

Por ejemplo, si el usuario está en el Fragmento A, luego desliza hacia la izquierda hasta el Fragmento B a un ritmo normal, y luego desliza rápidamente hacia la derecha para regresar al Fragmento A, luego en la pantalla se muestran ambos Fragmentos A y B.

¿Alguien tiene alguna idea sobre por qué sucede esto o una buena manera de prevenirlo?

Esto es lo que parece:

Aquí está mi definición de ViewPager en XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.company.views.CustomActionBar android:id="@+id/customActionBar" android:layout_width="match_parent" android:layout_height="@dimen/height_actionbar" android:layout_alignParentTop="true"/> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/customActionBar"/>

Además, registré la salida de mi onPageChangeListener () y noté que cuando el ViewPager se atasca entre las vistas, está reportando una posiciónOffset de 0. Esto es cómo se ven los valores del ViewPager cuando transita de STATE_DRAGGING a STATE_SETTLING a STATE_IDLE cuando aterriza en esto estado extraño

state = 0 prevState: 2 position: 1 positionOffset: 0.0

state = 1 prevState: 0 position: 1 positionOffset: 0.0

state = 2 prevState: 1 position: 1 positionOffset: 0.4069444

state = 0 prevState: 2 position: 2 positionOffset: 0.0

Así que parece que ViewPager está reportando la posición incorrecta Desactivada para mí.

Código de muestra completa de Actividad y Adaptador:

public class ActivityBagelProfileViewer extends CustomAbstractFragmentActivity implements CustomActionBarContract, ListenerProgress, ListenerSync { public static final String EXTRA_BAGEL_INDEX = "BAGEL"; public static final int REQUEST_CODE_BAGEL_PROFILE_VIEWER = 4000; public static final int RESULT_GO_TO_PASS_FLOW = 12; public static final int RESULT_GO_TO_LIKE_FLOW = 14; public static final int RESULT_GO_TO_SEE_MORE_BAGELS = 16; private ViewPager mProfilesViewPager; private CustomActionBar mCustomActionBar; private int mViewPagerPosition; private DialogProgress mDialogProgress; private BagelViewPagerAdapter mAdapterBagelViewPager; private List<Bagel> mListBagels; @Override protected void onCreate(Bundle savedInstanceState) { Logger.d("ENTER"); super.onCreate(savedInstanceState); if (ManagerGive.IS_BRANCH_SESSION_OPEN == false) { ManagerGive.initializeBranchMetricsSession(); } setContentView(R.layout.activity_with_viewpager); mCustomActionBar = (CustomActionBar) findViewById(R.id.customActionBar); mCustomActionBar.setMenu(this); mProfilesViewPager = (ViewPager) findViewById(R.id.viewPager); if (getIntent().getExtras() != null) { mViewPagerPosition = getIntent().getExtras().getInt(EXTRA_BAGEL_INDEX, 0); } } @Override protected void onStop() { super.onStop(); ManagerGive.closeBranchMetricsSession(); } public void onIconClick(View view) { Logger.d("ENTER"); finishWithAnimation(); } private void finishWithAnimation() { setResult(RESULT_OK); finish(); overridePendingTransition(R.anim.slide_in_from_left, R.anim.slide_out_to_right); } @Override public void onBackPressed() { if (!super.handleBackPressedEvent()) { finishWithAnimation(); } } private void setupNewAdapter() { mListBagels = Bakery.getInstance().getManagerBagel().getCopyOfBagelsWithoutCurrent(); mAdapterBagelViewPager = new BagelViewPagerAdapter(getSupportFragmentManager(), mListBagels, this); mProfilesViewPager.setAdapter(mAdapterBagelViewPager); mProfilesViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { setActionBar(position); mViewPagerPosition = position; } @Override public void onPageScrollStateChanged(int state) { } }); mProfilesViewPager.setCurrentItem(mViewPagerPosition, false); } @Override protected void onResume() { Logger.d("ENTER"); super.onResume(); Bakery.getInstance().getManagerSyncData().addListener(this); if (mProfilesViewPager.getAdapter() == null) { Logger.d("Adapter null. Setting new adapter"); setupNewAdapter(); } else { if (mProfilesViewPager.getAdapter().getCount() != Bakery.getInstance().getManagerBagel().getCopyOfBagelsWithoutCurrent().size()) { Logger.d("Bagel list in Bakery changed size. Setting new adapter"); setupNewAdapter(); } } if (mListBagels.size() > 0) { setActionBar(mViewPagerPosition); mDialogProgress = new DialogProgress(this); } else { //kv Something has gone terribly wrong if we don''t have any Bagels, just finish finish(); } } private void setActionBar(int bagelIndex) { Logger.d("bagelIndex=" + bagelIndex); Bagel bagel = mListBagels.get(bagelIndex); //kv If this is our current bagel and we haven''t taken action yet, then show timer if (Bakery.getInstance().getManagerBagel().getCurrentBagel() == bagel && bagel.getAction() != Bagel.ACTION_LIKED && bagel.getAction() != Bagel.ACTION_PASSED) { Logger.d("Setting up #timer in action bar"); mCustomActionBar.startTimeLeftTimer(DateUtils.getMillisFromUtc(bagel.getEndDate()), this, new ListenerTimer() { @Override public void onTimerExpired() { Logger.d("ENTER"); Bakery.getInstance().getManagerSyncData().performSync(null, false); } }, mCustomActionBar.getTextViewTimeLeft(), R.string.timer_blank); mCustomActionBar.setLabel(R.string.time_left); mCustomActionBar.hideTitle(); } //kv Otherwise show date else { mCustomActionBar.setTitle(DateUtils.getLocalizedDateFromStringDate(bagel.getStartDate(), DateUtils.DATE_WITH_TIME_PATTERN)); mCustomActionBar.stopTimeLeftTimer(); mCustomActionBar.hideTimeLeft(); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(EXTRA_BAGEL_INDEX, mViewPagerPosition); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { Logger.d("ENTER"); super.onRestoreInstanceState(savedInstanceState); if (savedInstanceState.containsKey(EXTRA_BAGEL_INDEX)) { mViewPagerPosition = savedInstanceState.getInt(EXTRA_BAGEL_INDEX); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Logger.d("requestCode=" + requestCode + ", resultCode=" + resultCode + ", data=" + data); switch (requestCode) { case ActivityBeanShop.REQUEST_CODE: if (resultCode == Activity.RESULT_OK && data != null) { //fp user purchased sufficient beans to resume their transaction PurchaseType interruptedPurchaseType = (PurchaseType) data.getSerializableExtra(ActivityBeanShop.EXTRA_PURCHASE_TYPE); switch (interruptedPurchaseType) { case BONUS_BAGEL: case OPEN_SESAME: case REMATCH: Bundle bundle = new Bundle(); bundle.putSerializable(ManagerPurchase.EXTRA_PURCHASE_TYPE, interruptedPurchaseType); ManagerEvents.notifyListeners(EventType.BEAN_TRANSACTION_FOR_FEATURE_UNLOCK_COMPLETE, bundle); Logger.d("Notified listeners about #purchase bean transaction, can now resume feature #purchase"); break; default: Logger.w("Unrecognized purchase type: " + interruptedPurchaseType.getItemName()); } } break; default: Logger.w("Could not recognize code: " + requestCode); } } @Override public int getTitleId() { return R.string.bagel_action_checked; } @Override public int getIconId() { return R.drawable.selector_icon_up; } @Override public void showProgress(int stringId) { mDialogProgress.setText(stringId); mDialogProgress.show(); } @Override public void dismissProgress() { ViewUtils.safelyDismissDialog(mDialogProgress); } public void setActionBar() { setActionBar(mViewPagerPosition); } @Override public void onSyncComplete() { Logger.d("ENTER"); mListBagels = Bakery.getInstance().getManagerBagel().getCopyOfBagelsWithoutCurrent(); mAdapterBagelViewPager.setBagels(mListBagels); } public boolean isShowingThisBagel(Bagel bagel) { Bagel currentlyShownBagel = mListBagels.get(mViewPagerPosition); return bagel == currentlyShownBagel; } private static class BagelViewPagerAdapter extends FragmentStatePagerAdapter { private List<Bagel> mBagels; private ListenerProgress mListenerProgress; public BagelViewPagerAdapter(FragmentManager fragmentManager, List<Bagel> bagels, ListenerProgress listenerProgress) { super(fragmentManager); Logger.d("bagels=" + bagels); this.mBagels = bagels; mListenerProgress = listenerProgress; } @Override public Fragment getItem(int i) { Logger.d("i=" + i); UserProfile myProfile = Bakery.getInstance().getManagerUserProfile().getMyOwnProfile(); FragmentProfile fragment = FragmentProfile.newInstance(mBagels.get(i), false, myProfile); fragment.setListenerProgress(mListenerProgress); return fragment; } @Override public int getCount() { return mBagels.size(); } public void setBagels(List<Bagel> bagels) { mBagels = bagels; notifyDataSetChanged(); } } }

Y aquí está el código de diseño XML para el diseño de cada Fragmento (tuvo que reducir algunos b / c del límite de caracteres SO):

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollView"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="-0.5dp" android:orientation="vertical" android:animateLayoutChanges="true" android:id="@+id/profile_top_container"> <!-- Photos section with pager/carousel --> <FrameLayout android:id="@+id/photoViewpagerContainer" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.coffeemeetsbagel.views.CustomAsShitViewPager android:id="@+id/pager_profile_images" xmlns:android="http://schemas.android.com/apk/res/android" app:aspectRatio="@integer/photo_ratio_height_over_width" android:layout_width="match_parent" android:layout_height="wrap_content"/> <LinearLayout android:id="@+id/linearLayout_bulletsAndFriendsContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="bottom"> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/textView_stamp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" app:customFont="Raleway-Bold.ttf" android:layout_gravity="end" android:textSize="@dimen/text_stamp" android:paddingTop="@dimen/margin_large" android:layout_marginEnd="@dimen/margin_xxxxxsmall" android:layout_marginRight="@dimen/profile_margin_smaller"/> <!-- photo circle indicators --> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/bullet_indicators" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/circle_indicator_margin_bottom" android:clickable="false" app:fillColor="@color/blue_cmb" app:pageColor="@color/gray_background" app:radius="@dimen/circle_indicator_radius" app:strokeWidth="0dp"/> <!-- container for mutual friends strip --> <RelativeLayout android:id="@+id/relativeLayout_mutual_friends_container" android:layout_width="match_parent" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/white_transparent" android:visibility="gone"> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/textView_mutual_friends_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignParentLeft="true" style="@style/profile_mutual_friends_text"/> <LinearLayout android:id="@+id/linearLayout_mutual_friends_icons" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_marginEnd="@dimen/baseline_grid_small" android:layout_marginRight="@dimen/baseline_grid_small" android:layout_centerVertical="true"> <ImageView android:id="@+id/imageView_icon0" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:padding="@dimen/typography_smallest" android:background="@color/transparent" android:visibility="gone"/> <ImageView android:id="@+id/imageView_icon1" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/transparent" android:padding="@dimen/typography_smallest" android:visibility="gone"/> <ImageView android:id="@+id/imageView_icon2" android:layout_width="@dimen/baseline_grid_component_touchable" android:layout_height="@dimen/baseline_grid_component_touchable" android:background="@color/transparent" android:padding="@dimen/typography_smallest" android:visibility="gone"/> </LinearLayout> </RelativeLayout> </LinearLayout> </FrameLayout> <!-- Buttons section with User Actions for pass / like--> <LinearLayout android:id="@+id/linearLayout_buttons_pass_like" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/baseline_grid_smaller" android:layout_marginLeft="@dimen/baseline_grid_small" android:layout_marginRight="@dimen/baseline_grid_small" android:layout_marginTop="@dimen/baseline_grid_medium" android:orientation="horizontal" android:visibility="gone"> <ImageView android:id="@+id/button_pass" android:layout_width="0dp" android:layout_height="@dimen/profile_action_button_height" android:layout_weight="1" android:background="@drawable/ripple_button_pass" android:clickable="true" android:src="@drawable/icon_pass_pressed" android:scaleType="center" android:layout_marginRight="@dimen/margin_small"/> <ImageView android:id="@+id/button_like" android:layout_width="0dp" android:layout_height="@dimen/profile_action_button_height" android:layout_weight="1" android:background="@drawable/ripple_button_like" android:clickable="true" android:src="@drawable/icon_like_pressed" android:scaleType="center" android:layout_marginLeft="@dimen/margin_small"/> </LinearLayout> <!-- Buttons section with User Actions for rematch / give--> <LinearLayout android:id="@+id/linearLayout_buttons_rematch_give" android:layout_width="match_parent" android:layout_height="@dimen/give_ten_button_height" android:layout_marginBottom="@dimen/baseline_grid_smaller" android:layout_marginLeft="@dimen/baseline_grid_small" android:layout_marginRight="@dimen/baseline_grid_small" android:layout_marginTop="@dimen/baseline_grid_medium" android:orientation="horizontal" android:gravity="center" android:visibility="gone"> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/textView_rematch" android:layout_width="@dimen/zero_dip" android:layout_height="match_parent" android:layout_marginRight="@dimen/give_take_button_margin_side" android:layout_weight="1" style="@style/button_give_take_rematch" android:text="@string/rematch"/> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/text_view_give_with_rematch" android:layout_width="@dimen/zero_dip" android:layout_weight="1" android:layout_height="match_parent" style="@style/button_give_take_rematch" android:text="@string/give"/> </LinearLayout> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/textView_they_like_you" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableLeft="@drawable/icon_like_alert" android:drawablePadding="@dimen/margin_xxsmall" style="@style/profile_info_item_value" android:layout_marginLeft="@dimen/margin_med" android:paddingTop="@dimen/baseline_grid_smaller"/> <ViewStub android:id="@+id/viewStub_profile_feedback" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout="@layout/profile_feedback"/> <!-- Profile information table --> <!-- Name --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:paddingTop="@dimen/baseline_grid_smaller" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_name" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_name" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Age --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_age" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_age" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Location --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/location" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_location" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Ethnicity --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_ethnicity" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_ethnicity" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Height --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_height" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_height" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Religion --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_religion" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_religion" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Occupation --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal"> <com.coffeemeetsbagel.views.CustomTextView android:text="@string/profile_info_label_occupation" style="@style/profile_info_item_label" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" /> <com.coffeemeetsbagel.views.CustomTextView android:id="@+id/profile_info_value_occupation" style="@style/profile_info_item_value" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2"/> </LinearLayout> <!-- Employer --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/profile_info_item_layout_margins" android:orientation="horizontal">

...


Acabo de onCreate cuenta de que está haciendo mucho trabajo de UI en onCreate () en la Actividad principal. Es más apropiado hacer el trabajo en onCreateView (). Creo que el marco de Android no termina de hacer el trabajo de la interfaz de usuario en onCreate () y, por lo tanto, se ve la representación de la interfaz de usuario incompleta. Sé que esto no está claramente establecido en la documentación de Android. Si verifica otras publicaciones de SO o proyectos de muestra, otros desarrolladores hacen poco trabajo de UI en onCreate (). Al menos, los diseños son más simples que los tuyos.

Aquí está mi sugerencia. fragtest diseño de fragtest en una Actividad o Fragmento en el método onCreateView (), usando el ID que se indica en la publicación. Observe que el método de anulación solo se infla. Código de muestra:

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragtest, container, false); }

En un Fragmento, comience a acceder a los elementos de la IU y al ViewPager, usando la ID que se indica en la publicación. Código de muestra:

@Override public void onViewCreated(View view, Bundle savedInstanceState) { mProfilesViewPager = (ViewPager) findViewById(R.id.viewPager); ...


Me he dado cuenta de que veo este problema si tengo algunas animaciones dadas por animateLayoutChanges . Simplemente desactivándolo en el archivo xml, evita que las páginas se atasquen en el medio.


Por ahora, estoy pensando que hay un problema con el ancho del diseño. Hasta ahora solo veo un sospechoso, hay un atributo desconocido

app:aspectRatio="@integer/photo_ratio_height_over_width"

en el elemento UI <com.coffeemeetsbagel.views.CustomAsShitViewPager ...

Al parecer, hay un atributo personalizado en la biblioteca / código CustomAsShitViewPager, tal vez publicar el código relacionado con aspectRatio, al menos.


Pruebe el siguiente código de muestra y modifíquelo según sus requisitos (supongo que está cargando la imagen en el subproceso de la interfaz de usuario principal y no la está almacenando en caché, es solo una conjetura). En este código estoy descargando y almacenando en caché las imágenes de Internet: Crear una clase de actividad llamada SomeFragTest

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.app.ActivityManager; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.util.LruCache; import android.support.v4.view.ViewPager; import android.util.Log; import android.widget.ImageView; public class SomeFragTest extends FragmentActivity{ private LruCache<String, Bitmap> cache; private List<String> strings; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); ViewPager mViewPager = (ViewPager)findViewById(R.id.viewPager); strings=new ArrayList<String>(); setData(); int memClass = ( ( ActivityManager )getSystemService( Context.ACTIVITY_SERVICE ) ).getMemoryClass(); int cacheSize = 1024 * 1024 * memClass / 8; cache=new LruCache<String, Bitmap>(cacheSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getByteCount()/1024; } }; mViewPager.setOffscreenPageLimit(strings.size()); mViewPager.setAdapter(new MyPageAdapter(getSupportFragmentManager())); } private void setData() { for (int i = 1; i <= 10; i++) { strings.add("http://dummyimage.com/600x400/000/0011ff.png&text="+i); } } public void loadBitmap(int position , ImageView imageView) { imageView.setImageResource(R.drawable.ic_launcher); imageView.setTag(strings.get(position)); BitmapDownloaderTask task = new BitmapDownloaderTask(imageView); task.execute(strings.get(position)); } class MyPageAdapter extends FragmentPagerAdapter { public MyPageAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } @Override public Fragment getItem(int arg0) { Fragment fragment=new ChildFrag(); Bundle bundle=new Bundle(); bundle.putInt("POS", arg0); fragment.setArguments(bundle); return fragment; } @Override public int getCount() { return strings.size(); } } class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> { public String url; private final WeakReference<ImageView> imageViewReference; public BitmapDownloaderTask(ImageView imageView) { imageViewReference = new WeakReference<ImageView>(imageView); } @Override // Actual download method, run in the task thread protected Bitmap doInBackground(String... params) { // params comes from the execute() call: params[0] is the url. url=params[0]; if(cache.get(url)!=null){ Log.e("FROM ", "CACHE"); return cache.get(url); } return downloadBitmap(params[0]); } private Bitmap downloadBitmap(String url) { Log.e("FROM ", "URL"); HttpClient client=new DefaultHttpClient(); //final AndroidHttpClient client = AndroidHttpClient.newInstance("Android"); final HttpGet getRequest = new HttpGet(url); try { HttpResponse response = client.execute(getRequest); final int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != HttpStatus.SC_OK) { Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); return null; } final HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); //final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return decodeBitmapWithGiveSizeFromResource(inputStream); } finally { if (inputStream != null) { inputStream.close(); } entity.consumeContent(); } } } catch (Exception e) { // Could provide a more explicit error message for IOException or IllegalStateException getRequest.abort(); Log.w("ImageDownloader", "Error while retrieving bitmap from " + url); Log.e("ERROR", " " +e.getLocalizedMessage()); } finally { if (client != null) { //client.close(); } } return null; } /***************/ private void copy(InputStream inputStream,ByteArrayOutputStream arrayOutputStream) { byte[] buffer = new byte[1024]; int len; try { while ((len = inputStream.read(buffer)) > -1 ) { arrayOutputStream.write(buffer, 0, len); } arrayOutputStream.flush(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private Bitmap decodeBitmapWithGiveSizeFromResource(InputStream inputStream) { //BufferedInputStream bufferedInputStream=new BufferedInputStream(inputStream); final BitmapFactory.Options options = new BitmapFactory.Options(); ByteArrayOutputStream out = new ByteArrayOutputStream(); copy(inputStream,out); InputStream in2 = new ByteArrayInputStream(out.toByteArray()); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(inputStream, null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; Bitmap bitmap=BitmapFactory.decodeStream(in2,null, options); try { inputStream.close(); in2.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return scaleDown(bitmap,false); } private Bitmap scaleDown(Bitmap realImage, boolean filter) { Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, 100, 100, filter); Bitmap output = Bitmap.createBitmap(newBitmap.getWidth(), newBitmap .getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, newBitmap.getWidth(), newBitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = 10; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(newBitmap, rect, rect, paint); return output; } private int calculateInSampleSize(BitmapFactory.Options options) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > 100 || width > 100) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) >100 && (halfWidth / inSampleSize) >100) { inSampleSize *= 2; } } return inSampleSize; } @Override // Once the image is downloaded, associates it to the imageView protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { cache.put(url, bitmap); ImageView imageView = imageViewReference.get(); // BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); // Change bitmap only if this process is still associated with it if (((String)imageView.getTag()).equalsIgnoreCase(url)) { imageView.setImageBitmap(bitmap); } } } } }

Después de esto crea el xml para ello, llamado activity_layout

<?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:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>

Ahora hemos creado la clase Fragmento que queremos inflar en el ViewPager: Cree una clase llamada ChildFrag de la siguiente manera

import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; public class ChildFrag extends Fragment { private int index; private ImageView imageView; @Override @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragtest, container, false); index = getArguments().getInt("POS"); ((TextView) view.findViewById(R.id.textView1)).setText("" + index); imageView = (ImageView) view.findViewById(R.id.imageView1); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ((SomeFragTest) getActivity()).loadBitmap(index, imageView); } }

Ahora hemos creado el xml para el fragmento como fragtest:

<?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:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> </LinearLayout>

Agregue el siguiente permiso en el AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />


Por ahora, sospecho dos métodos.

1) En el código del fragmento:

@Override public int getCount() { return mBagels.size(); }

Nota: getCount()debe devolver el número de fragmentos en lugar del tamaño de la lista. No podría decir cuántos fragmentos tendrás. Quizás tengas que seguir la pista en el adaptador.

2) Otro, sospecho getItem()método y el uso de newInstance(). El código específico relacionado:

FragmentProfile fragment = FragmentProfile.newInstance(mBagels.get(i),...

Notas :

  • De acuerdo con la página web FragmentStatePagerAdapter Google , el método newInstancedebería crear un nuevo fragmento probablemente porque es cuando el FragmentStatePagerAdapter aún no tiene el fragmento en la memoria O se lanzó de la memoria.

  • Quizás publique el código relacionado FragmentProfile.newInstanceespecialmente si no está de acuerdo con mi declaración anterior.