Jimit Patel
Jimit Patel

Reputation: 4297

ViewPager with Rotational transformation

I want to create ViewPager which on swipe rotates around it's getWidth() and getHeight() axis. I tried but all those transformation were only possible with vertical and horizontal with various effect.

Is there any way or hint to develop such kind of ViewPager?

EDIT- Explanation for what kind of rotation it would be

Axis - getWidth, getHeight should be pivot point from which once I swipe it should rotate and for next page it should rotate in from (0, getHeight) axis. To simplify, consider this simple scenario -

  1. There is a circle with 4 parts into it
  2. Currently only 1 part is being displayed and other 3 are outside screen
  3. Once I swipe right to left, ViewPager should rotate from page 1 to page 2.
  4. If I swipe from left to right, ViewPager should rotate from page 1 to page 4.
  5. Both exiting and entering pages should rotate from center of that circle everytime.
  6. Center of the circle is at getWidth, getHeight of the 1st page. So for next page it will always be 0, getHeight as axis and for previous page is will be always getWidth, 0 as axis.

Upvotes: 4

Views: 1343

Answers (1)

UPDATE As far as I read, you want a transition like that. Implemented a ViewPager.PageTransformer as you see below.

enter image description here

Here is the ViewPager.PageTransformer class:

public class RotationCircleTransformer implements ViewPager.PageTransformer {


    public RotationCircleTransformer() {
    }

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();
        view.setPivotX((float) pageWidth);
        view.setPivotY((float) pageHeight);

        if (position < -1) { //[-infinity,1)
            //off to the left by a lot
            view.setRotation(0);
            view.setAlpha(0);
        } else if (position <= 1) { //[-1,1]
            view.setTranslationX((-position) * pageWidth); //shift the view over
            view.setRotation(position * (90)); //rotate it
            // Fade the page relative to its distance from the center
            view.setAlpha(Math.max(1, 1 - Math.abs(position) / 3));
        } else { //(1, +infinity]
            //off to the right by a lot
            view.setRotation(0);
            view.setAlpha(0);
        }
    }
}

background_quarter.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <size android:height="300dp" android:width="300dp"/>
    <solid android:color="#00F"/>
    <corners android:topLeftRadius="300dp" android:topRightRadius="0dp" android:bottomRightRadius="0dp" android:bottomLeftRadius="0dp"/>
</shape>

activity_circle_pager.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_gravity="center"
        android:layout_width="300dp"
        android:layout_height="300dp" />


</FrameLayout>

fragment_content.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:id="@+id/bg"
    android:background="@drawable/background_quarter">

    <TextView
        android:id="@+id/text"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="40dp"
        android:textColor="@android:color/white"
        android:text="" />

</FrameLayout>

CircleFragment.class

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;


public class CircleFragment extends Fragment {

    private String typeString;

    public CircleFragment() {
    }

    public static CircleFragment newInstance(String type) {
        CircleFragment fragment = new CircleFragment();
        Bundle args = new Bundle();
        args.putString("type", type);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            typeString = getArguments().getString("type","1");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_content, container, false);
        ;
        TextView text = (TextView) view.findViewById(R.id.text);
        FrameLayout bg = (FrameLayout) view.findViewById(R.id.bg);
        switch (typeString) {
            case "1":
                bg.setBackgroundDrawable(ContextCompat.getDrawable(getContext(), R.drawable.background_quarter));
                break;
            case "2":
                bg.setBackgroundDrawable(ContextCompat.getDrawable(getContext(), R.drawable.background_quarter));
                break;
            case "3":
                bg.setBackgroundDrawable(ContextCompat.getDrawable(getContext(), R.drawable.background_quarter));
                break;
            case "4":
                bg.setBackgroundDrawable(ContextCompat.getDrawable(getContext(), R.drawable.background_quarter));
                break;
        }
        text.setText(typeString);
        return view;
    }

}

CirclePagerActivity.class

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

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

public class CirclePagerActivity extends AppCompatActivity {

    ViewPager mPager;
    CirclePagerAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circle_pager);
        mPager = (ViewPager) findViewById(R.id.pager);
        List<Fragment> fragments = new ArrayList<>();
        fragments.add(ContentFragment.newInstance("1"));
        fragments.add(ContentFragment.newInstance("2"));
        fragments.add(ContentFragment.newInstance("3"));
        fragments.add(ContentFragment.newInstance("4"));
        mAdapter = new CirclePagerAdapter(getSupportFragmentManager(), fragments);
        mPager.setAdapter(mAdapter);

        mPager.setPageTransformer(true, new RotationCircleTransformer());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    static class CirclePagerAdapter extends FragmentStatePagerAdapter {

        List<Fragment> mFrags = new ArrayList<>();

        public CirclePagerAdapter(FragmentManager fm, List<Fragment> frags) {
            super(fm);
            mFrags = frags;
        }

        @Override
        public Fragment getItem(int position) {
            int index = position % mFrags.size();
            return mFrags.get(index);
        }

        @Override
        public int getCount() {
            return Integer.MAX_VALUE;
        }

    }
}

If you do not find a suitable ViewPager transformation animation, you can implement your own ViewPager.PageTransformer

There is a lot of information and multiple example for that.

Also here you can find a useful tutorial.


Can you explain more detailed about this part? I will update my answer according to your explanation (Visual explenation is better).

rotates around it's getWidth() and getHeight() axis.

Upvotes: 5

Related Questions