Java – Flip images in viewpager

Flip images in viewpager… here is a solution to the problem.

Flip images in viewpager

I have a viewpager for a full-screen image slider that slides horizontally. What I want to do is put an image after each image on the slider. That is, the user can click the “Flip” button to display another picture.

Below is my code, but I have two questions:

  1. The first time I hit the flip button, it flipped the image, but only
    Display the same image. However, when I click on it for the second time
    Useful :).
  2. The flip button is only available for the first image. When I swipe
    Flipping the button right or left no longer works. Does it help?

Note: I’m using the fullscreenActivity theme, which hides UI controls until the user clicks the image.

FullscreenActivity.java

package me.zamaaan.wallpaper;

import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import me.zamaaan.wallpaper.util.SystemUiHider;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import static me.zamaaan.wallpaper.HeavyLifter.FAIL;
import static me.zamaaan.wallpaper.HeavyLifter.SUCCESS;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;

import java.util.ArrayList;
import java.util.List;

/** A helper class that will do the heavy work of decoding images and actually setting the wallpaper */

/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 * 
 * @see SystemUiHider
 */
public class FullscreenActivity extends Activity implements OnClickListener, AnimationListener{
    /**
     * Whether or not the system UI should be auto-hidden after
     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
     */
    private static final boolean AUTO_HIDE = true;
    private HeavyLifter chuckNorris;
    private Animation animation1;
    private Animation animation2;
    private boolean isBackOfCardShowing = true;

/*
    an array with the ids of the images for the viewpager

*/
    public Integer[] mImageIds = {
            R.drawable.background1, R.drawable.background2,
            R.drawable.background3, R.drawable.background4,
            R.drawable.background1, R.drawable.background2,
            R.drawable.background1, R.drawable.background2,
            R.drawable.background3, R.drawable.background4,
            R.drawable.background1, R.drawable.background2,
            R.drawable.background3
    };
    /*
    an array with the ids of the images for the back flip of each image in the viewpager
     */
    public Integer[] mBackIds = {
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash, R.drawable.splash,
            R.drawable.splash
    };

/**
     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
     * user interaction before hiding the system UI.
     */
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

/**
     * If set, will toggle the system UI visibility upon interaction. Otherwise,
     * will show the system UI visibility upon interaction.
     */
    private static final boolean TOGGLE_ON_CLICK = true;

/**
     * The flags to pass to {@link SystemUiHider#getInstance}.
     */
    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;

/**
     * The instance of the {@link SystemUiHider} for this activity.
     */
    private SystemUiHider mSystemUiHider;

/**
     * The pager widget, which handles animation and allows swiping horizontally to access previous
     * and next wizard steps.
     */
    private ViewPager mPager;

/**
     * The pager adapter, which provides the pages to the view pager widget.
     */
    private PagerAdapter mPagerAdapter;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

setContentView(R.layout.activity_fullscreen);
        animation1 = AnimationUtils.loadAnimation(this, R.anim.to_middle);
        animation1.setAnimationListener(this);
        animation2 = AnimationUtils.loadAnimation(this, R.anim.from_middle);
        animation2.setAnimationListener(this);
        findViewById(R.id.flip).setOnClickListener(this);

 Loop through the ids to create a list of full screen image views
        ImageAdapter imageAdapter = new ImageAdapter(this);
        List<ImageView> images = new ArrayList<ImageView>();

for (int i = 0; i < imageAdapter.getCount(); i++) {
            ImageView imageView = new ImageView(this);
            imageView.setId(i);
            imageView.setImageResource(imageAdapter.mThumbIds[i]);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            images.add(imageView);
        }

final View controlsView = findViewById(R.id.fullscreen_content_controls);
        final View contentView = findViewById(R.id.view_pager);

 Set up an instance of SystemUiHider to control the system UI for
         this activity.
        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
        mSystemUiHider.setup();
        mSystemUiHider.setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
                     Cached values.
                    int mControlsHeight;
                    int mShortAnimTime;

@Override
                    @TargetApi(Build.VERSION_CODES. HONEYCOMB_MR2)
                    public void onVisibilityChange(boolean visible) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES. HONEYCOMB_MR2) {
                             If the ViewPropertyAnimator API is available
                             (Honeycomb MR2 and later), use it to animate the
                             in-layout UI controls at the bottom of the
                             screen.
                            if (mControlsHeight == 0) {
                                mControlsHeight = controlsView.getHeight();
                            }
                            if (mShortAnimTime == 0) {
                                mShortAnimTime = getResources().getInteger(
                                        android. R.integer.config_shortAnimTime);
                            }
                            controlsView
                                    .animate()
                                    .translationY(visible ? 0 : mControlsHeight)
                                    .setDuration(mShortAnimTime);
                        } else {
                             If the ViewPropertyAnimator APIs aren't
                             available, simply show or hide the in-layout UI
                             controls.
                            controlsView.setVisibility(visible ? View.VISIBLE
                                    : View.GONE);
                        }

if (visible && AUTO_HIDE) {
                             Schedule a hide().
                            delayedHide(AUTO_HIDE_DELAY_MILLIS);
                        }
                    }
                });

 Set up the user interaction to manually show or hide the system UI.
        contentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mSystemUiHider.toggle();
                } else {
                    mSystemUiHider.show();
                }
            }
        });

 Upon interacting with UI controls, delay any scheduled hide()
         operations to prevent the jarring behavior of controls going away
         while interacting with the UI.
        findViewById(R.id.btnSetAsWallpaper).setOnTouchListener(
                mDelayHideTouchListener);
        findViewById(R.id.btnSaveWallpaper).setOnTouchListener(
                mDelayHideTouchListener);

 Finally create the adapter
        ImagePagerAdapter imagePagerAdapter = new ImagePagerAdapter(images);
        ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
        viewPager.setAdapter(imagePagerAdapter);

 Set the ViewPager to point to the selected image from the previous activity
         Selected image id
        int position = getIntent().getExtras().getInt("id");
        viewPager.setCurrentItem(position);
        set title of Image
        this.setTitle(imageAdapter.mThumbTitles[position]);
         Load are heavy lifter (goes and does work on another thread), to get a response after the lifters thread
         has finished we pass in a Handler that will be notified when it completes
        chuckNorris = new HeavyLifter(this, chuckFinishedHandler);

}

@Override
    public void onClick(View v) {
        v.setEnabled(false);
        ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).clearAnimation();
        ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).setAnimation(animation1);
        ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).startAnimation(animation1);
    }
    @Override
    public void onAnimationEnd(Animation animation) {
        int i = getIntent().getExtras().getInt("id");
        if (animation==animation1) {
            if (isBackOfCardShowing) {
                ((ImageView)findViewById(i)).setImageResource(mImageIds[i]);
            } else {
                ((ImageView)findViewById(i)).setImageResource(mBackIds[i]);
            }
            ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).clearAnimation();
            ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).setAnimation(animation2);
            ((ImageView)findViewById(getIntent().getExtras().getInt("id"))).startAnimation(animation2);
        } else {
            isBackOfCardShowing=!isBackOfCardShowing;
            findViewById(R.id.flip).setEnabled(true);
        }
    }

@Override
    public void onAnimationRepeat(Animation animation) {
         TODO Auto-generated method stub

}

@Override
    public void onAnimationStart(Animation animation) {
         TODO Auto-generated method stub

}
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

 Trigger the initial hide() shortly after the activity has been
         created, to briefly hint to the user that UI controls
         are available.
        delayedHide(100);
    }

/**
     * Touch listener to use for in-layout UI controls to delay hiding the
     * system UI. This is to prevent the jarring behavior of controls going away
     * while interacting with activity UI.
     */
    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            return false;
        }
    };

Handler mHideHandler = new Handler();
    Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            mSystemUiHider.hide();
        }
    };

/**
     * Schedules a call to hide() in [delay] milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

/**
     * Called from XML when the save wallpaper button is pressed
     * Thie retrieves the id of the current image from our list
     * It then asks chuck to save it as a wallpaper!
     * The chuckHandler will be called when this operation is complete
     * @param v
     */

public void saveWallpaper(View v) {
          get intent data
        Intent i = getIntent();

 Selected image id
        int position = i.getExtras().getInt("id");
        ImageAdapter imageAdapter = new ImageAdapter(this);

 Show a toast message on successful save
        if(chuckNorris.saveResourceAsWallpaper(imageAdapter.mThumbIds[position])){
            Toast.makeText(FullscreenActivity.this, "Image Saved to ZamaaanWallpaper folder", Toast.LENGTH_SHORT).show();
        }
        else{
            Toast.makeText(FullscreenActivity.this, "Image couldn't be saved, try again", Toast.LENGTH_SHORT).show();
        }

}

/**
     * Called from XML when the set wallpaper button is pressed
     * Thie retrieves the id of the current image from our list
     * It then asks chuck to set it as a wallpaper!
     * The chuckHandler will be called when this operation is complete
     * @param v
     */
    public void setAsWallpaper(View v) {
          get intent data
        Intent i = getIntent();

 Selected image id
        int position = i.getExtras().getInt("id");
        ImageAdapter imageAdapter = new ImageAdapter(this);

chuckNorris.setResourceAsWallpaper(imageAdapter.mThumbIds[position]);
    }

/**
     * This is the handler that is notified when are HeavyLifter is finished doing an operation
     */
    private Handler chuckFinishedHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what){
            case SUCCESS:
                Toast.makeText(FullscreenActivity.this, "Wallpaper set", Toast.LENGTH_SHORT).show();
                break;
            case FAIL:
                Toast.makeText(FullscreenActivity.this, "Wallper NOT set, try again", Toast.LENGTH_SHORT).show();
                break;
            default:
                super.handleMessage(msg);
            }
        }
    };

}

Solution

I solved my problem. I just need :

  1. Change the boolean isBackOfCardShowing of each page to a boolean array and initialize it to false.
  2. Use viewpager.getCurrentItem() to get the location of the current page, not what I’m doing.

Related Problems and Solutions