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
newInstance
deberí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.newInstance
especialmente si no está de acuerdo con mi declaración anterior.