├── README.md
├── android-page-transition
├── .gitignore
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── stone
│ │ │ └── transition
│ │ │ └── ApplicationTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ │ ├── image1.jpg
│ │ │ ├── image2.jpg
│ │ │ ├── image3.jpg
│ │ │ ├── image4.jpg
│ │ │ └── image5.jpg
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── stone
│ │ │ │ └── transition
│ │ │ │ ├── AspectRatioCardView.java
│ │ │ │ ├── CommonFragment.java
│ │ │ │ ├── CustPagerTransformer.java
│ │ │ │ ├── DetailActivity.java
│ │ │ │ ├── DragLayout.java
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable-xxhdpi
│ │ │ ├── background.jpg
│ │ │ ├── close.png
│ │ │ ├── gps.png
│ │ │ ├── head1.png
│ │ │ ├── head2.png
│ │ │ ├── head3.png
│ │ │ ├── head4.png
│ │ │ ├── icon1.png
│ │ │ ├── icon2.png
│ │ │ ├── icon3.png
│ │ │ ├── like.png
│ │ │ ├── paper_background.png
│ │ │ ├── search.png
│ │ │ ├── three_dot.png
│ │ │ └── white_back.9.png
│ │ │ ├── layout
│ │ │ ├── activity_detail.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── detail_list_item.xml
│ │ │ └── fragment_common.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── attrs.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── stone
│ │ └── transition
│ │ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── capture1.jpg
├── gif1.gif
├── gif2.gif
├── gif3.gif
└── pageTransition.apk
/README.md:
--------------------------------------------------------------------------------
1 | # android-page-transition
2 | viewpager with vertical sliding effects and activity transition
3 |
4 |
5 |
6 |
7 |
8 |
9 | The original design is here: https://dribbble.com/shots/2493845-ToFind-Transition-Test
10 |
11 | #### Captured images:
12 |
13 |
14 |
15 |
16 | #### Coding design
17 | Sliding pages to the left or right, as we know, could be implemented by using ViewPager. And fortunately, ViewPager's PagerTransformer is allowed for customization. That's to say, [CustPagerTransformer](android-page-transition/app/src/main/java/com/stone/transition/CustPagerTransformer.java) could get rid of all the parallax effects.
18 | Then, in viewpager's fragment item, vertical slide is an independent module, which could be realized by using ViewDragHelper. In the activity transition part, android OS (above 5.0) makes it easy to transfer to another activity.
19 |
20 | #### Thanks
21 | [rubensousa/ViewPagerCards](https://github.com/rubensousa/ViewPagerCards)
22 | [antoniolg/MaterialEverywhere](https://github.com/antoniolg/MaterialEverywhere)
23 |
24 | #### Demo Apk
25 | [download](https://github.com/xmuSistone/android-page-transition/blob/master/pageTransition.apk?raw=true)
26 |
27 | ### Version: 1.0
28 |
29 | * Pilot version
30 |
31 | ## License
32 |
33 | Copyright 2016, xmuSistone
34 |
35 | Licensed under the Apache License, Version 2.0 (the "License");
36 | you may not use this file except in compliance with the License.
37 | You may obtain a copy of the License at
38 |
39 | http://www.apache.org/licenses/LICENSE-2.0
40 |
41 | Unless required by applicable law or agreed to in writing, software
42 | distributed under the License is distributed on an "AS IS" BASIS,
43 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44 | See the License for the specific language governing permissions and
45 | limitations under the License.
46 |
47 |
48 |
49 | [1]: http://square.github.com/dagger/
50 |
51 |
--------------------------------------------------------------------------------
/android-page-transition/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/android-page-transition/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/android-page-transition/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.stone.transition"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.2.0'
26 | compile 'com.android.support:cardview-v7:23.2.0'
27 | compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
28 | }
29 |
--------------------------------------------------------------------------------
/android-page-transition/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\adt-bundle-windows-x86-20130917\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/androidTest/java/com/stone/transition/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/assets/image1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/assets/image1.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/assets/image2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/assets/image2.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/assets/image3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/assets/image3.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/assets/image4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/assets/image4.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/assets/image5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/assets/image5.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/AspectRatioCardView.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.CardView;
5 | import android.util.AttributeSet;
6 | import android.view.ViewGroup;
7 |
8 | /**
9 | * 锁定宽高比的CardView
10 | * Created by xmuSistone on 2016/9/21.
11 | */
12 | public class AspectRatioCardView extends CardView {
13 |
14 | private float ratio = 1.2f;
15 |
16 | public AspectRatioCardView(Context context) {
17 | this(context, null);
18 | }
19 |
20 | public AspectRatioCardView(Context context, AttributeSet attrs) {
21 | this(context, attrs, 0);
22 | }
23 |
24 | public AspectRatioCardView(Context context, AttributeSet attrs, int defStyleAttr) {
25 | super(context, attrs, defStyleAttr);
26 | }
27 |
28 | @Override
29 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
30 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
31 | if (ratio > 0) {
32 | int ratioHeight = (int) (getMeasuredWidth() * ratio);
33 | setMeasuredDimension(getMeasuredWidth(), ratioHeight);
34 | ViewGroup.LayoutParams lp = getLayoutParams();
35 | lp.height = ratioHeight;
36 | setLayoutParams(lp);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/CommonFragment.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.ActivityCompat;
8 | import android.support.v4.app.ActivityOptionsCompat;
9 | import android.support.v4.app.Fragment;
10 | import android.support.v4.util.Pair;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.ImageView;
15 | import android.widget.RatingBar;
16 |
17 | import com.nostra13.universalimageloader.core.ImageLoader;
18 |
19 | /**
20 | * Created by xmuSistone on 2016/9/18.
21 | */
22 | public class CommonFragment extends Fragment implements DragLayout.GotoDetailListener {
23 | private ImageView imageView;
24 | private View address1, address2, address3, address4, address5;
25 | private RatingBar ratingBar;
26 | private View head1, head2, head3, head4;
27 | private String imageUrl;
28 |
29 | @Nullable
30 | @Override
31 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
32 | View rootView = inflater.inflate(R.layout.fragment_common, null);
33 | DragLayout dragLayout = (DragLayout) rootView.findViewById(R.id.drag_layout);
34 | imageView = (ImageView) dragLayout.findViewById(R.id.image);
35 | ImageLoader.getInstance().displayImage(imageUrl, imageView);
36 | address1 = dragLayout.findViewById(R.id.address1);
37 | address2 = dragLayout.findViewById(R.id.address2);
38 | address3 = dragLayout.findViewById(R.id.address3);
39 | address4 = dragLayout.findViewById(R.id.address4);
40 | address5 = dragLayout.findViewById(R.id.address5);
41 | ratingBar = (RatingBar) dragLayout.findViewById(R.id.rating);
42 |
43 | head1 = dragLayout.findViewById(R.id.head1);
44 | head2 = dragLayout.findViewById(R.id.head2);
45 | head3 = dragLayout.findViewById(R.id.head3);
46 | head4 = dragLayout.findViewById(R.id.head4);
47 |
48 | dragLayout.setGotoDetailListener(this);
49 | return rootView;
50 | }
51 |
52 | @Override
53 | public void gotoDetail() {
54 | Activity activity = (Activity) getContext();
55 | ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
56 | new Pair(imageView, DetailActivity.IMAGE_TRANSITION_NAME),
57 | new Pair(address1, DetailActivity.ADDRESS1_TRANSITION_NAME),
58 | new Pair(address2, DetailActivity.ADDRESS2_TRANSITION_NAME),
59 | new Pair(address3, DetailActivity.ADDRESS3_TRANSITION_NAME),
60 | new Pair(address4, DetailActivity.ADDRESS4_TRANSITION_NAME),
61 | new Pair(address5, DetailActivity.ADDRESS5_TRANSITION_NAME),
62 | new Pair(ratingBar, DetailActivity.RATINGBAR_TRANSITION_NAME),
63 | new Pair(head1, DetailActivity.HEAD1_TRANSITION_NAME),
64 | new Pair(head2, DetailActivity.HEAD2_TRANSITION_NAME),
65 | new Pair(head3, DetailActivity.HEAD3_TRANSITION_NAME),
66 | new Pair(head4, DetailActivity.HEAD4_TRANSITION_NAME)
67 | );
68 | Intent intent = new Intent(activity, DetailActivity.class);
69 | intent.putExtra(DetailActivity.EXTRA_IMAGE_URL, imageUrl);
70 | ActivityCompat.startActivity(activity, intent, options.toBundle());
71 | }
72 |
73 | public void bindData(String imageUrl) {
74 | this.imageUrl = imageUrl;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/CustPagerTransformer.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.view.View;
6 |
7 | /**
8 | * 实现ViewPager左右滑动时的时差
9 | * Created by xmuSistone on 2016/9/18.
10 | */
11 | public class CustPagerTransformer implements ViewPager.PageTransformer {
12 |
13 | private int maxTranslateOffsetX;
14 | private ViewPager viewPager;
15 |
16 | public CustPagerTransformer(Context context) {
17 | this.maxTranslateOffsetX = dp2px(context, 180);
18 | }
19 |
20 | public void transformPage(View view, float position) {
21 | if (viewPager == null) {
22 | viewPager = (ViewPager) view.getParent();
23 | }
24 |
25 | int leftInScreen = view.getLeft() - viewPager.getScrollX();
26 | int centerXInViewPager = leftInScreen + view.getMeasuredWidth() / 2;
27 | int offsetX = centerXInViewPager - viewPager.getMeasuredWidth() / 2;
28 | float offsetRate = (float) offsetX * 0.38f / viewPager.getMeasuredWidth();
29 | float scaleFactor = 1 - Math.abs(offsetRate);
30 | if (scaleFactor > 0) {
31 | view.setScaleX(scaleFactor);
32 | view.setScaleY(scaleFactor);
33 | view.setTranslationX(-maxTranslateOffsetX * offsetRate);
34 | }
35 | }
36 |
37 | /**
38 | * dp和像素转换
39 | */
40 | private int dp2px(Context context, float dipValue) {
41 | float m = context.getResources().getDisplayMetrics().density;
42 | return (int) (dipValue * m + 0.5f);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/DetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.support.v4.view.ViewCompat;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.Window;
11 | import android.view.WindowManager;
12 | import android.widget.ImageView;
13 | import android.widget.LinearLayout;
14 | import android.widget.RatingBar;
15 |
16 | import com.nostra13.universalimageloader.core.ImageLoader;
17 |
18 | /**
19 | * Created by xmuSistone on 2016/9/19.
20 | */
21 | public class DetailActivity extends FragmentActivity {
22 |
23 | public static final String EXTRA_IMAGE_URL = "detailImageUrl";
24 |
25 | public static final String IMAGE_TRANSITION_NAME = "transitionImage";
26 | public static final String ADDRESS1_TRANSITION_NAME = "address1";
27 | public static final String ADDRESS2_TRANSITION_NAME = "address2";
28 | public static final String ADDRESS3_TRANSITION_NAME = "address3";
29 | public static final String ADDRESS4_TRANSITION_NAME = "address4";
30 | public static final String ADDRESS5_TRANSITION_NAME = "address5";
31 | public static final String RATINGBAR_TRANSITION_NAME = "ratingBar";
32 |
33 | public static final String HEAD1_TRANSITION_NAME = "head1";
34 | public static final String HEAD2_TRANSITION_NAME = "head2";
35 | public static final String HEAD3_TRANSITION_NAME = "head3";
36 | public static final String HEAD4_TRANSITION_NAME = "head4";
37 |
38 | private View address1, address2, address3, address4, address5;
39 | private ImageView imageView;
40 | private RatingBar ratingBar;
41 |
42 | private LinearLayout listContainer;
43 | private static final String[] headStrs = {HEAD1_TRANSITION_NAME, HEAD2_TRANSITION_NAME, HEAD3_TRANSITION_NAME, HEAD4_TRANSITION_NAME};
44 | private static final int[] imageIds = {R.drawable.head1, R.drawable.head2, R.drawable.head3, R.drawable.head4};
45 |
46 | @Override
47 | protected void onCreate(@Nullable Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_detail);
50 |
51 | imageView = (ImageView) findViewById(R.id.image);
52 | address1 = findViewById(R.id.address1);
53 | address2 = findViewById(R.id.address2);
54 | address3 = findViewById(R.id.address3);
55 | address4 = findViewById(R.id.address4);
56 | address5 = findViewById(R.id.address5);
57 | ratingBar = (RatingBar) findViewById(R.id.rating);
58 | listContainer = (LinearLayout) findViewById(R.id.detail_list_container);
59 |
60 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
61 | Window window = getWindow();
62 | window.setFlags(
63 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
64 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
65 | }
66 |
67 | String imageUrl = getIntent().getStringExtra(EXTRA_IMAGE_URL);
68 | ImageLoader.getInstance().displayImage(imageUrl, imageView);
69 |
70 | ViewCompat.setTransitionName(imageView, IMAGE_TRANSITION_NAME);
71 | ViewCompat.setTransitionName(address1, ADDRESS1_TRANSITION_NAME);
72 | ViewCompat.setTransitionName(address2, ADDRESS2_TRANSITION_NAME);
73 | ViewCompat.setTransitionName(address3, ADDRESS3_TRANSITION_NAME);
74 | ViewCompat.setTransitionName(address4, ADDRESS4_TRANSITION_NAME);
75 | ViewCompat.setTransitionName(address5, ADDRESS5_TRANSITION_NAME);
76 | ViewCompat.setTransitionName(ratingBar, RATINGBAR_TRANSITION_NAME);
77 |
78 | dealListView();
79 | }
80 |
81 | private void dealListView() {
82 | LayoutInflater layoutInflater = LayoutInflater.from(this);
83 |
84 | for (int i = 0; i < 20; i++) {
85 | View childView = layoutInflater.inflate(R.layout.detail_list_item, null);
86 | listContainer.addView(childView);
87 | ImageView headView = (ImageView) childView.findViewById(R.id.head);
88 | if (i < headStrs.length) {
89 | headView.setImageResource(imageIds[i % imageIds.length]);
90 | ViewCompat.setTransitionName(headView, headStrs[i]);
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/DragLayout.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.support.v4.view.GestureDetectorCompat;
6 | import android.support.v4.view.ViewCompat;
7 | import android.support.v4.widget.ViewDragHelper;
8 | import android.util.AttributeSet;
9 | import android.view.GestureDetector;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 | import android.view.ViewConfiguration;
13 | import android.widget.FrameLayout;
14 |
15 | /**
16 | * 尽量考虑了所有操作系统版本的分辨率适配
17 | * Created by xmuSistone on 2016/9/18.
18 | */
19 | public class DragLayout extends FrameLayout {
20 |
21 | private int bottomDragVisibleHeight; // 滑动可见的高度
22 | private int bototmExtraIndicatorHeight; // 底部指示器的高度
23 | private int dragTopDest = 0; // 顶部View滑动的目标位置
24 | private static final int DECELERATE_THRESHOLD = 120;
25 | private static final int DRAG_SWITCH_DISTANCE_THRESHOLD = 100;
26 | private static final int DRAG_SWITCH_VEL_THRESHOLD = 800;
27 |
28 | private static final float MIN_SCALE_RATIO = 0.5f;
29 | private static final float MAX_SCALE_RATIO = 1.0f;
30 |
31 | private static final int STATE_CLOSE = 1;
32 | private static final int STATE_EXPANDED = 2;
33 | private int downState; // 按下时的状态
34 |
35 | private final ViewDragHelper mDragHelper;
36 | private final GestureDetectorCompat moveDetector;
37 | private int mTouchSlop = 5; // 判定为滑动的阈值,单位是像素
38 | private int originX, originY; // 初始状态下,topView的坐标
39 | private View bottomView, topView; // FrameLayout的两个子View
40 |
41 | private GotoDetailListener gotoDetailListener;
42 |
43 | public DragLayout(Context context) {
44 | this(context, null);
45 | }
46 |
47 | public DragLayout(Context context, AttributeSet attrs) {
48 | this(context, attrs, 0);
49 | }
50 |
51 | public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {
52 | super(context, attrs, defStyleAttr);
53 |
54 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.app, 0, 0);
55 | bottomDragVisibleHeight = (int) a.getDimension(R.styleable.app_bottomDragVisibleHeight, 0);
56 | bototmExtraIndicatorHeight = (int) a.getDimension(R.styleable.app_bototmExtraIndicatorHeight, 0);
57 | a.recycle();
58 |
59 | mDragHelper = ViewDragHelper
60 | .create(this, 10f, new DragHelperCallback());
61 | mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_TOP);
62 | moveDetector = new GestureDetectorCompat(context, new MoveDetector());
63 | moveDetector.setIsLongpressEnabled(false); // 不处理长按事件
64 |
65 | // 滑动的距离阈值由系统提供
66 | ViewConfiguration configuration = ViewConfiguration.get(getContext());
67 | mTouchSlop = configuration.getScaledTouchSlop();
68 | }
69 |
70 | @Override
71 | protected void onFinishInflate() {
72 | super.onFinishInflate();
73 | bottomView = getChildAt(0);
74 | topView = getChildAt(1);
75 |
76 | topView.setOnClickListener(new View.OnClickListener() {
77 | @Override
78 | public void onClick(View v) {
79 | // 点击回调
80 | int state = getCurrentState();
81 | if (state == STATE_CLOSE) {
82 | // 点击时为初始状态,需要展开
83 | if (mDragHelper.smoothSlideViewTo(topView, originX, dragTopDest)) {
84 | ViewCompat.postInvalidateOnAnimation(DragLayout.this);
85 | }
86 | } else {
87 | // 点击时为展开状态,直接进入详情页
88 | gotoDetailActivity();
89 | }
90 | }
91 | });
92 | }
93 |
94 | // 跳转到下一页
95 | private void gotoDetailActivity() {
96 | if (null != gotoDetailListener) {
97 | gotoDetailListener.gotoDetail();
98 | }
99 | }
100 |
101 | private class DragHelperCallback extends ViewDragHelper.Callback {
102 |
103 | @Override
104 | public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
105 | if (changedView == topView) {
106 | processLinkageView();
107 | }
108 | }
109 |
110 | @Override
111 | public boolean tryCaptureView(View child, int pointerId) {
112 | if (child == topView) {
113 | return true;
114 | }
115 | return false;
116 | }
117 |
118 | @Override
119 | public int clampViewPositionVertical(View child, int top, int dy) {
120 | int currentTop = child.getTop();
121 | if (top > child.getTop()) {
122 | // 往下拉的时候,阻力最小
123 | return currentTop + (top - currentTop) / 2;
124 | }
125 |
126 | int result;
127 | if (currentTop > DECELERATE_THRESHOLD * 3) {
128 | result = currentTop + (top - currentTop) / 2;
129 | } else if (currentTop > DECELERATE_THRESHOLD * 2) {
130 | result = currentTop + (top - currentTop) / 4;
131 | } else if (currentTop > 0) {
132 | result = currentTop + (top - currentTop) / 8;
133 | } else if (currentTop > -DECELERATE_THRESHOLD) {
134 | result = currentTop + (top - currentTop) / 16;
135 | } else if (currentTop > -DECELERATE_THRESHOLD * 2) {
136 | result = currentTop + (top - currentTop) / 32;
137 | } else if (currentTop > -DECELERATE_THRESHOLD * 3) {
138 | result = currentTop + (top - currentTop) / 48;
139 | } else {
140 | result = currentTop + (top - currentTop) / 64;
141 | }
142 | return result;
143 | }
144 |
145 | @Override
146 | public int clampViewPositionHorizontal(View child, int left, int dx) {
147 | return child.getLeft();
148 | }
149 |
150 | @Override
151 | public int getViewHorizontalDragRange(View child) {
152 | return 600;
153 | }
154 |
155 | @Override
156 | public int getViewVerticalDragRange(View child) {
157 | return 600;
158 | }
159 |
160 | @Override
161 | public void onViewReleased(View releasedChild, float xvel, float yvel) {
162 | int finalY = originY;
163 | if (downState == STATE_CLOSE) {
164 | // 按下的时候,状态为:初始状态
165 | if (originY - releasedChild.getTop() > DRAG_SWITCH_DISTANCE_THRESHOLD || yvel < -DRAG_SWITCH_VEL_THRESHOLD) {
166 | finalY = dragTopDest;
167 | }
168 | } else {
169 | // 按下的时候,状态为:展开状态
170 | boolean gotoBottom = releasedChild.getTop() - dragTopDest > DRAG_SWITCH_DISTANCE_THRESHOLD || yvel > DRAG_SWITCH_VEL_THRESHOLD;
171 | if (!gotoBottom) {
172 | finalY = dragTopDest;
173 |
174 | // 如果按下时已经展开,又向上拖动了,就进入详情页
175 | if (dragTopDest - releasedChild.getTop() > mTouchSlop) {
176 | gotoDetailActivity();
177 | postResetPosition();
178 | return;
179 | }
180 | }
181 | }
182 |
183 | if (mDragHelper.smoothSlideViewTo(releasedChild, originX, finalY)) {
184 | ViewCompat.postInvalidateOnAnimation(DragLayout.this);
185 | }
186 | }
187 | }
188 |
189 |
190 | private void postResetPosition() {
191 | this.postDelayed(new Runnable() {
192 | @Override
193 | public void run() {
194 | topView.offsetTopAndBottom(dragTopDest - topView.getTop());
195 | }
196 | }, 500);
197 | }
198 |
199 | /**
200 | * 顶层ImageView位置变动,需要对底层的view进行缩放显示
201 | */
202 | private void processLinkageView() {
203 | if (topView.getTop() > originY) {
204 | bottomView.setAlpha(0);
205 | } else {
206 | float alpha = (originY - topView.getTop()) * 0.01f;
207 | if (alpha > 1) {
208 | alpha = 1;
209 | }
210 | bottomView.setAlpha(alpha);
211 | int maxDistance = originY - dragTopDest;
212 | int currentDistance = topView.getTop() - dragTopDest;
213 | float scaleRatio = 1;
214 | float distanceRatio = (float) currentDistance / maxDistance;
215 | if (currentDistance > 0) {
216 | scaleRatio = MIN_SCALE_RATIO + (MAX_SCALE_RATIO - MIN_SCALE_RATIO) * (1 - distanceRatio);
217 | }
218 | bottomView.setScaleX(scaleRatio);
219 | bottomView.setScaleY(scaleRatio);
220 | }
221 | }
222 |
223 | class MoveDetector extends GestureDetector.SimpleOnGestureListener {
224 | @Override
225 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx,
226 | float dy) {
227 | // 拖动了,touch不往下传递
228 | return Math.abs(dy) + Math.abs(dx) > mTouchSlop;
229 | }
230 | }
231 |
232 | @Override
233 | public void computeScroll() {
234 | if (mDragHelper.continueSettling(true)) {
235 | ViewCompat.postInvalidateOnAnimation(this);
236 | }
237 | }
238 |
239 | /**
240 | * 获取当前状态
241 | */
242 | private int getCurrentState() {
243 | int state;
244 | if (Math.abs(topView.getTop() - dragTopDest) <= mTouchSlop) {
245 | state = STATE_EXPANDED;
246 | } else {
247 | state = STATE_CLOSE;
248 | }
249 | return state;
250 | }
251 |
252 |
253 | @Override
254 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
255 | if (!changed) {
256 | return;
257 | }
258 |
259 | super.onLayout(changed, left, top, right, bottom);
260 |
261 | originX = (int) topView.getX();
262 | originY = (int) topView.getY();
263 | dragTopDest = bottomView.getBottom() - bottomDragVisibleHeight - topView.getMeasuredHeight();
264 | }
265 |
266 | /* touch事件的拦截与处理都交给mDraghelper来处理 */
267 | @Override
268 | public boolean onInterceptTouchEvent(MotionEvent ev) {
269 | // 1. detector和mDragHelper判断是否需要拦截
270 | boolean yScroll = moveDetector.onTouchEvent(ev);
271 | boolean shouldIntercept = false;
272 | try {
273 | shouldIntercept = mDragHelper.shouldInterceptTouchEvent(ev);
274 | } catch (Exception e) {
275 | }
276 |
277 | // 2. 触点按下的时候直接交给mDragHelper
278 | int action = ev.getActionMasked();
279 | if (action == MotionEvent.ACTION_DOWN) {
280 | downState = getCurrentState();
281 | mDragHelper.processTouchEvent(ev);
282 | }
283 |
284 | return shouldIntercept && yScroll;
285 | }
286 |
287 | @Override
288 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
289 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
290 |
291 | // bottomMarginTop高度的计算,还是需要有一个清晰的数学模型才可以。
292 | // 实现的效果,是topView.top和bottomView.bottom展开前、与展开后都整体居中
293 | int bottomMarginTop = (bottomDragVisibleHeight + topView.getMeasuredHeight() / 2 - bottomView.getMeasuredHeight() / 2) / 2 - bototmExtraIndicatorHeight;
294 | FrameLayout.LayoutParams lp1 = (LayoutParams) bottomView.getLayoutParams();
295 | lp1.setMargins(0, bottomMarginTop, 0, 0);
296 | bottomView.setLayoutParams(lp1);
297 | }
298 |
299 | @Override
300 | public boolean onTouchEvent(MotionEvent e) {
301 | // 统一交给mDragHelper处理,由DragHelperCallback实现拖动效果
302 | try {
303 | mDragHelper.processTouchEvent(e);
304 | } catch (Exception ex) {
305 | ex.printStackTrace();
306 | }
307 | return true;
308 | }
309 |
310 | public void setGotoDetailListener(GotoDetailListener gotoDetailListener) {
311 | this.gotoDetailListener = gotoDetailListener;
312 | }
313 |
314 | public interface GotoDetailListener {
315 | public void gotoDetail();
316 | }
317 | }
318 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/java/com/stone/transition/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import android.graphics.Color;
4 | import android.os.Build;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.app.FragmentActivity;
7 | import android.support.v4.app.FragmentPagerAdapter;
8 | import android.support.v4.app.FragmentStatePagerAdapter;
9 | import android.support.v4.view.ViewPager;
10 | import android.support.v7.app.AppCompatActivity;
11 | import android.os.Bundle;
12 | import android.text.Html;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.view.Window;
16 | import android.view.WindowManager;
17 | import android.widget.TextView;
18 |
19 | import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
20 | import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
21 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
22 | import com.nostra13.universalimageloader.core.ImageLoader;
23 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
24 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
25 | import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
26 |
27 | import java.lang.reflect.Field;
28 | import java.util.ArrayList;
29 | import java.util.List;
30 |
31 |
32 | /**
33 | * Created by xmuSistone on 2016/9/18.
34 | */
35 | public class MainActivity extends FragmentActivity {
36 |
37 | private TextView indicatorTv;
38 | private View positionView;
39 | private ViewPager viewPager;
40 | private List fragments = new ArrayList<>(); // 供ViewPager使用
41 | private final String[] imageArray = {"assets://image1.jpg", "assets://image2.jpg", "assets://image3.jpg", "assets://image4.jpg", "assets://image5.jpg"};
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.activity_main);
47 |
48 | // 1. 沉浸式状态栏
49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
50 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
51 | getWindow().setStatusBarColor(Color.TRANSPARENT);
52 | getWindow()
53 | .getDecorView()
54 | .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
55 | } else {
56 | getWindow()
57 | .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
58 | }
59 | }
60 | positionView = findViewById(R.id.position_view);
61 | dealStatusBar(); // 调整状态栏高度
62 |
63 | // 2. 初始化ImageLoader
64 | initImageLoader();
65 |
66 | // 3. 填充ViewPager
67 | fillViewPager();
68 | }
69 |
70 | /**
71 | * 填充ViewPager
72 | */
73 | private void fillViewPager() {
74 | indicatorTv = (TextView) findViewById(R.id.indicator_tv);
75 | viewPager = (ViewPager) findViewById(R.id.viewpager);
76 |
77 | // 1. viewPager添加parallax效果,使用PageTransformer就足够了
78 | viewPager.setPageTransformer(false, new CustPagerTransformer(this));
79 |
80 | // 2. viewPager添加adapter
81 | for (int i = 0; i < 10; i++) {
82 | // 预先准备10个fragment
83 | fragments.add(new CommonFragment());
84 | }
85 |
86 | viewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) {
87 | @Override
88 | public Fragment getItem(int position) {
89 | CommonFragment fragment = fragments.get(position % 10);
90 | fragment.bindData(imageArray[position % imageArray.length]);
91 | return fragment;
92 | }
93 |
94 | @Override
95 | public int getCount() {
96 | return 666;
97 | }
98 | });
99 |
100 |
101 | // 3. viewPager滑动时,调整指示器
102 | viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
103 | @Override
104 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
105 | }
106 |
107 | @Override
108 | public void onPageSelected(int position) {
109 | updateIndicatorTv();
110 | }
111 |
112 | @Override
113 | public void onPageScrollStateChanged(int state) {
114 |
115 | }
116 | });
117 |
118 | updateIndicatorTv();
119 | }
120 |
121 | /**
122 | * 更新指示器
123 | */
124 | private void updateIndicatorTv() {
125 | int totalNum = viewPager.getAdapter().getCount();
126 | int currentItem = viewPager.getCurrentItem() + 1;
127 | indicatorTv.setText(Html.fromHtml("" + currentItem + " / " + totalNum));
128 | }
129 |
130 | /**
131 | * 调整沉浸式菜单的title
132 | */
133 | private void dealStatusBar() {
134 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
135 | int statusBarHeight = getStatusBarHeight();
136 | ViewGroup.LayoutParams lp = positionView.getLayoutParams();
137 | lp.height = statusBarHeight;
138 | positionView.setLayoutParams(lp);
139 | }
140 | }
141 |
142 | private int getStatusBarHeight() {
143 | Class> c = null;
144 | Object obj = null;
145 | Field field = null;
146 | int x = 0, statusBarHeight = 0;
147 | try {
148 | c = Class.forName("com.android.internal.R$dimen");
149 | obj = c.newInstance();
150 | field = c.getField("status_bar_height");
151 | x = Integer.parseInt(field.get(obj).toString());
152 | statusBarHeight = getResources().getDimensionPixelSize(x);
153 | } catch (Exception e1) {
154 | e1.printStackTrace();
155 | }
156 | return statusBarHeight;
157 | }
158 |
159 | @SuppressWarnings("deprecation")
160 | private void initImageLoader() {
161 | ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
162 | this)
163 | .memoryCacheExtraOptions(480, 800)
164 | // default = device screen dimensions
165 | .threadPoolSize(3)
166 | // default
167 | .threadPriority(Thread.NORM_PRIORITY - 1)
168 | // default
169 | .tasksProcessingOrder(QueueProcessingType.FIFO)
170 | // default
171 | .denyCacheImageMultipleSizesInMemory()
172 | .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
173 | .memoryCacheSize(2 * 1024 * 1024).memoryCacheSizePercentage(13) // default
174 | .discCacheSize(50 * 1024 * 1024) // 缓冲大小
175 | .discCacheFileCount(100) // 缓冲文件数目
176 | .discCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default
177 | .imageDownloader(new BaseImageDownloader(this)) // default
178 | .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default
179 | .writeDebugLogs().build();
180 |
181 | // 2.单例ImageLoader类的初始化
182 | ImageLoader imageLoader = ImageLoader.getInstance();
183 | imageLoader.init(config);
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/background.jpg
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/close.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/gps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/gps.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/head1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/head1.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/head2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/head2.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/head3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/head3.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/head4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/head4.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/icon1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/icon1.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/icon2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/icon2.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/icon3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/icon3.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/like.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/like.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/paper_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/paper_background.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/search.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/three_dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/three_dot.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/drawable-xxhdpi/white_back.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/drawable-xxhdpi/white_back.9.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/layout/activity_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
17 |
25 |
26 |
34 |
35 |
42 |
43 |
52 |
53 |
54 |
55 |
56 |
57 |
60 |
61 |
65 |
66 |
72 |
73 |
82 |
83 |
91 |
92 |
100 |
101 |
102 |
103 |
104 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
19 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
36 |
37 |
43 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
66 |
67 |
68 |
73 |
74 |
75 |
76 |
80 |
81 |
85 |
86 |
92 |
93 |
99 |
100 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/layout/detail_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
22 |
23 |
32 |
33 |
42 |
43 |
49 |
50 |
51 |
52 |
60 |
61 |
62 |
67 |
68 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/layout/fragment_common.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
15 |
16 |
17 |
18 |
24 |
25 |
31 |
32 |
43 |
44 |
52 |
53 |
61 |
62 |
69 |
70 |
71 |
72 |
77 |
78 |
86 |
87 |
92 |
93 |
99 |
100 |
106 |
107 |
113 |
114 |
118 |
119 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
142 |
143 |
148 |
149 |
154 |
155 |
163 |
164 |
171 |
172 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 150dp
6 | 20dp
7 |
8 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | pageTransition
3 |
4 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/android-page-transition/app/src/test/java/com/stone/transition/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.stone.transition;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/android-page-transition/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.1.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/android-page-transition/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/android-page-transition/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/android-page-transition/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android-page-transition/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/android-page-transition/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android-page-transition/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android-page-transition/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/capture1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/capture1.jpg
--------------------------------------------------------------------------------
/gif1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/gif1.gif
--------------------------------------------------------------------------------
/gif2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/gif2.gif
--------------------------------------------------------------------------------
/gif3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/gif3.gif
--------------------------------------------------------------------------------
/pageTransition.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xmuSistone/ViewpagerTransition/fa92d8296dbf22e4daef0fd2de7b35a587625ed9/pageTransition.apk
--------------------------------------------------------------------------------