Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: ViewPager gets stuck in between views

Tags:

I have a ViewPager which swipes between Fragments. I'm using a FragmentStatePagerAdapter to feed the Fragments to the ViewPager. If the user swipes left at a normal pace, and then swipes right very quickly, they can get the ViewPager into a weird state where it shows multiple Fragments.

For example, if the user is on Fragment A, then swipes left to Fragment B at a normal pace, and then quickly swipes right to go back to Fragment A, then on screen shows both Fragments A & B.

Anybody have any ideas on why this is happening or a good way to prevent it?

Here's what it looks like: enter image description here

Here's my ViewPager definition in 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"/> 

Also, I logged output from my onPageChangeListener() and noticed that when the ViewPager gets stuck in between views, it's reporting a positionOffset of 0. Here's what the ViewPager's values look like as it transitions from STATE_DRAGGING to STATE_SETTLING to STATE_IDLE when it lands in this weird state:

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

So it appears as if the ViewPager is reporting the wrong positionOffset back to me.

Full sample code Activity and Adapter:

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();     } } } 

And here's the XML layout code for the layout of each Fragment (had to cut some out b/c of SO char limit):

<?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"> 

...

like image 990
Karim Varela Avatar asked Jul 21 '15 21:07

Karim Varela


2 Answers

I've noticed that I see this issue if I have some animations given by the animateLayoutChanges. Just deactivating it in the xml file, prevents the pages to be stuck in the middle.

like image 129
Santacrab Avatar answered Nov 10 '22 09:11

Santacrab


Try the following sample code and modify it as per your requirement(I guess your are loading the image on main UI thread and not caching it, its just a guess). In this code i am downloading and caching the images from the internet : Create a Activity class named 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);          }     } }    } } 

After this create the xml for it, named 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> 

Now we have create the Fragment class that we want to inflate in the ViewPager: Create a class named ChildFrag as follows

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); } } 

Now we have create the xml for the fragment as 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> 

Add the following permission in the AndroidManifest.xml

 <uses-permission android:name="android.permission.INTERNET" /> 
like image 31
avinash Avatar answered Nov 10 '22 08:11

avinash