我有一个ViewPager片段之间刷卡。我使用的是FragmentStatePagerAdapter喂片段与ViewPager。如果留在一个正常的速度,然后用户扫描挥笔正确的速度非常快,他们可以得到ViewPager进入一个奇怪的状态,它显示了多个片段。
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.
例如,如果用户在碎片A,然后以正常速度刷卡左到碎片B,然后快速挥笔权要回去片段A,然后在屏幕上显示两个片段A和B点。
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.
任何人对为什么发生这种情况的任何想法或一个好方法prevent呢?
Anybody have any ideas on why this is happening or a good way to prevent it?
下面是什么样子:
Here's what it looks like:
下面是在XML我ViewPager定义:
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"/>
另外,我记录的输出从我onPageChangeListener(),并注意到,当ViewPager卡在视图之间,它的报告为0。positionOffset下面就是ViewPager的价值观样子,因为它从STATE_DRAGGING过渡到STATE_SETTLING到STATE_IDLE时,在这个奇怪的国有土地:
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:
状态= 0 prevState:2位:1 positionOffset:0.0
state = 0 prevState: 2 position: 1 positionOffset: 0.0
状态= 1 prevState:0位置:1 positionOffset:0.0
state = 1 prevState: 0 position: 1 positionOffset: 0.0
状态= 2 prevState:1位置:1 positionOffset:0.4069444
state = 2 prevState: 1 position: 1 positionOffset: 0.4069444
状态= 0 prevState:2位置:2 positionOffset:0.0
state = 0 prevState: 2 position: 2 positionOffset: 0.0
所以看起来好像ViewPager正在报告错误positionOffset回到我身边。
So it appears as if the ViewPager is reporting the wrong positionOffset back to me.
全样本code活性和适配器:
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();
}
}
}
和这里的XML布局code每个片段的布局(不得不削减一些出了这么字数不多于B / C):
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">
...
试试下面的示例code和修改它按照您的要求(我猜你是装在主UI线程的形象,而不是将其高速缓存,其只是一个猜测)。在这种$ C $词时下载并缓存来自互联网的图片: 创建一个名为SomeFragTest一个Activity类
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("https://m.xsw88.com/allimgs/daicuo/20230905/324.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);
}
}
}
}
}
在此创建XML为它命名为activity_layout
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>
现在我们必须创建一个我们要在ViewPager膨胀的片段类: 创建一个名为ChildFrag类如下:
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);
}
}
现在我们已经创建XML的片段作为fragtest:
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>
添加以下权限在AndroidManifest.xml
Add the following permission in the AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />