Android: Viewpager Gets Stuck In Between Views
Solution 1:
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.
Solution 2:
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;
publicclassSomeFragTestextendsFragmentActivity{
private LruCache<String, Bitmap> cache;
private List<String> strings;
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
ViewPagermViewPager= (ViewPager)findViewById(R.id.viewPager);
strings=newArrayList<String>();
setData();
intmemClass= ( ( ActivityManager )getSystemService( Context.ACTIVITY_SERVICE ) ).getMemoryClass();
intcacheSize=1024 * 1024 * memClass / 8;
cache=newLruCache<String, Bitmap>(cacheSize){
@OverrideprotectedintsizeOf(String key, Bitmap value) {
return value.getByteCount()/1024;
}
};
mViewPager.setOffscreenPageLimit(strings.size());
mViewPager.setAdapter(newMyPageAdapter(getSupportFragmentManager()));
}
privatevoidsetData()
{
for (inti=1; i <= 10; i++) {
strings.add("http://dummyimage.com/600x400/000/0011ff.png&text="+i);
}
}
publicvoidloadBitmap(int position , ImageView imageView) {
imageView.setImageResource(R.drawable.ic_launcher);
imageView.setTag(strings.get(position));
BitmapDownloaderTasktask=newBitmapDownloaderTask(imageView);
task.execute(strings.get(position));
}
classMyPageAdapterextendsFragmentPagerAdapter
{
publicMyPageAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Overridepublic Fragment getItem(int arg0) {
Fragment fragment=newChildFrag();
Bundle bundle=newBundle();
bundle.putInt("POS", arg0);
fragment.setArguments(bundle);
return fragment;
}
@OverridepublicintgetCount() {
return strings.size();
}
}
classBitmapDownloaderTaskextendsAsyncTask<String, Void, Bitmap> {
public String url;
privatefinal WeakReference<ImageView> imageViewReference;
publicBitmapDownloaderTask(ImageView imageView) {
imageViewReference = newWeakReference<ImageView>(imageView);
}
@Override// Actual download method, run in the task threadprotected 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=newDefaultHttpClient();
//final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");finalHttpGetgetRequest=newHttpGet(url);
try {
HttpResponseresponse= client.execute(getRequest);
finalintstatusCode= response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
returnnull;
}
finalHttpEntityentity= response.getEntity();
if (entity != null) {
InputStreaminputStream=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();
}
}
returnnull;
}
/***************/privatevoidcopy(InputStream inputStream,ByteArrayOutputStream arrayOutputStream)
{
byte[] buffer = newbyte[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.Optionsoptions=newBitmapFactory.Options();
ByteArrayOutputStreamout=newByteArrayOutputStream();
copy(inputStream,out);
InputStreamin2=newByteArrayInputStream(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) {
BitmapnewBitmap= Bitmap.createScaledBitmap(realImage, 100,
100, filter);
Bitmapoutput= Bitmap.createBitmap(newBitmap.getWidth(), newBitmap
.getHeight(), Config.ARGB_8888);
Canvascanvas=newCanvas(output);
finalintcolor=0xff424242;
finalPaintpaint=newPaint();
finalRectrect=newRect(0, 0, newBitmap.getWidth(), newBitmap.getHeight());
finalRectFrectF=newRectF(rect);
finalfloatroundPx=10;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(newPorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(newBitmap, rect, rect, paint);
return output;
}
privateintcalculateInSampleSize(BitmapFactory.Options options) {
// Raw height and width of imagefinalintheight= options.outHeight;
finalintwidth= options.outWidth;
intinSampleSize=1;
if (height > 100 || width > 100) {
finalinthalfHeight= height / 2;
finalinthalfWidth= 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 imageViewprotectedvoidonPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
cache.put(url, bitmap);
ImageViewimageView= imageViewReference.get();
// BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);// Change bitmap only if this process is still associated with itif (((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"?><LinearLayoutxmlns: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.ViewPagerandroid: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;
publicclassChildFragextendsFragment {
privateint index;
private ImageView imageView;
@Override@Nullablepublic View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Viewview= 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;
}
@OverridepublicvoidonActivityCreated(@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"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Large Text"android:textAppearance="?android:attr/textAppearanceLarge" /><ImageViewandroid: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-permissionandroid:name="android.permission.INTERNET" />
Solution 3:
In my case, the problem was an empty Fragment. After create a fragment with a layout, it's starts working as expected.
Basically, I used a empty fragment for test the view:
fragment = new Fragment(); //Strange behavior in ViewPager
When I used the final fragment which has a layout, the behavior was the correct:
fragment = MyFragment.newInstance(); //Correct behavior
I know that this response doesn't answer the current question, but some people with similar problems arrive here. So, I hope it's helpful.
Solution 4:
For now, I am thinking there is an issue with the width of the layout. So far I only see one suspect, there is an unknown attribute
app:aspectRatio="@integer/photo_ratio_height_over_width"
in UI element <com.coffeemeetsbagel.views.CustomAsShitViewPager
...
Apparently there is a custom attribute in library/code CustomAsShitViewPager, perhaps post the code related to aspectRatio, at least.
Solution 5:
I just realized that you're doing a lot of UI work in onCreate
() in the main Activity. It is more proper to do the work in onCreateView
(). I believe the Android framework is not finish doing the UI work in onCreate
() and therefore you see incomplete UI rendering.
I know this is not clearly stated in Android documentation. If you check other SO posts or sample projects, other developers do little UI work in onCreate
(). At least, the layouts are simpler than yours.
Here is my suggestion.
Inflate the fragtest
layout in an Activity or Fragment in method onCreateView
(), using the ID listed on post. Notice the override method only inflates.
Sample code:
@OverridepublicViewonCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragtest, container, false);
}
On a Fragment, start accessing the UI elements and the ViewPager, using the ID listed on post. Sample code:
@OverridepublicvoidonViewCreated(View view, Bundle savedInstanceState) {
mProfilesViewPager = (ViewPager) findViewById(R.id.viewPager);
...
Post a Comment for "Android: Viewpager Gets Stuck In Between Views"