Android共享元素场景切换动画的实现

安卓5.0系统引入了共享元素,能做出非常炫酷的场景切换效果,这让人非常兴奋同时非常蛋疼,因为低版本没法使用啊,所以今天就跟大家分享一下自己写的一个库,其实只有2个文件而已就可以兼容安卓5.0以下的版本。


重要的工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
import android.animation.Animator;
import android.animation.TimeInterpolator;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.ViewTreeObserver;
 
import java.util.ArrayList;
 
/**
 * Tool for transition between two activities
 * <br/>
 * Created by huzn on 2017/5/8.
 */
public class EasyTransition {
 
    public static final String EASY_TRANSITION_OPTIONS = "easy_transition_options";
    public static final long DEFAULT_TRANSITION_ANIM_DURATION = 1000;
 
    /**
     * Start Activity with transition options
     *
     * @param intent  The intent to start
     * @param options Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
     *                to build your options
     */
    public static void startActivity(Intent intent, EasyTransitionOptions options) {
        options.update();
        intent.putParcelableArrayListExtra(EASY_TRANSITION_OPTIONS, options.getAttrs());
        Activity activity = options.getActivity();
        activity.startActivity(intent);
        activity.overridePendingTransition(0, 0);
    }
 
    /**
     * Start Activity for result, with transition options
     *
     * @param intent      The intent to start
     * @param requestCode If >= 0, this code will be returned in onActivityResult() when the activity exits,
     *                    see {@link Activity#startActivityForResult(Intent, int)}
     * @param options     Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
     *                    to build your options
     */
    public static void startActivityForResult(Intent intent, int requestCode, EasyTransitionOptions options) {
        options.update();
        intent.putParcelableArrayListExtra(EASY_TRANSITION_OPTIONS, options.getAttrs());
        Activity activity = options.getActivity();
        activity.startActivityForResult(intent, requestCode);
        activity.overridePendingTransition(0, 0);
    }
 
    /**
     * Enter the Activity, invoking this method to start enter transition animations
     *
     * @param activity     The Activity entering
     * @param duration     The duration of enter transition animation
     * @param interpolator The TimeInterpolator of enter transition animation
     * @param listener     Animator listener, normally you can do your initial after animation end
     */
    public static void enter(Activity activity, long duration, TimeInterpolator interpolator, Animator.AnimatorListener listener) {
        Intent intent = activity.getIntent();
        ArrayList<EasyTransitionOptions.ViewAttrs> attrs =
                intent.getParcelableArrayListExtra(EASY_TRANSITION_OPTIONS);
        runEnterAnimation(activity, attrs, duration, interpolator, listener);
    }
 
    /**
     * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
     * with no interpolator
     */
    public static void enter(Activity activity, long duration, Animator.AnimatorListener listener) {
        enter(activity, duration, null, listener);
    }
 
    /**
     * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
     * with default duration
     */
    public static void enter(Activity activity, TimeInterpolator interpolator, Animator.AnimatorListener listener) {
        enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, interpolator, listener);
    }
 
    /**
     * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
     * with default duration and no interpolator
     */
    public static void enter(Activity activity, Animator.AnimatorListener listener) {
        enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, null, listener);
    }
 
    /**
     * The same as {@link EasyTransition#enter(Activity, long, TimeInterpolator, Animator.AnimatorListener)}
     * with default duration, no interpolator and no listener
     */
    public static void enter(Activity activity) {
        enter(activity, DEFAULT_TRANSITION_ANIM_DURATION, null, null);
    }
 
    private static void runEnterAnimation(Activity activity,
                                          ArrayList<EasyTransitionOptions.ViewAttrs> attrs,
                                          final long duration,
                                          final TimeInterpolator interpolator,
                                          final Animator.AnimatorListener listener) {
        if (null == attrs || attrs.size() == 0)
            return;
 
        for (final EasyTransitionOptions.ViewAttrs attr : attrs) {
            final View view = activity.findViewById(attr.id);
 
            if (null == view)
                continue;
 
            view.getViewTreeObserver()
                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                        @Override
                        public boolean onPreDraw() {
                            view.getViewTreeObserver().removeOnPreDrawListener(this);
 
                            int[] location = new int[2];
                            view.getLocationOnScreen(location);
                            view.setPivotX(0);
                            view.setPivotY(0);
                            view.setScaleX(attr.width / view.getWidth());
                            view.setScaleY(attr.height / view.getHeight());
                            view.setTranslationX(attr.startX - location[0]); // xDelta
                            view.setTranslationY(attr.startY - location[1]); // yDelta
 
                            view.animate()
                                    .scaleX(1)
                                    .scaleY(1)
                                    .translationX(0)
                                    .translationY(0)
                                    .setDuration(duration)
                                    .setInterpolator(interpolator)
                                    .setListener(listener);
                            return true;
                        }
                    });
        }
    }
 
    /**
     * Exit the Activity, invoke this method to start exit transition animation,
     * the shared views must have same ids, or it will throws NullPointerException
     *
     * @param activity     The Activity Exiting
     * @param interpolator The TimeInterpolator of exit transition animation
     * @param duration     The duration of exit transition animation
     * @throws NullPointerException throws if shared views not found in The Activity Exiting
     */
    public static void exit(Activity activity, long duration, TimeInterpolator interpolator) {
        Intent intent = activity.getIntent();
        ArrayList<EasyTransitionOptions.ViewAttrs> attrs = intent.getParcelableArrayListExtra(EASY_TRANSITION_OPTIONS);
        runExitAnimation(activity, attrs, duration, interpolator);
    }
 
    /**
     * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
     * with default duration
     */
    public static void exit(Activity activity, TimeInterpolator interpolator) {
        exit(activity, DEFAULT_TRANSITION_ANIM_DURATION, interpolator);
    }
 
    /**
     * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
     * with no interpolator
     */
    public static void exit(Activity activity, long duration) {
        exit(activity, duration, null);
    }
 
    /**
     * The same as {@link EasyTransition#exit(Activity, long, TimeInterpolator)}
     * with default duration and no interpolator
     */
    public static void exit(Activity activity) {
        exit(activity, DEFAULT_TRANSITION_ANIM_DURATION, null);
    }
 
    private static void runExitAnimation(final Activity activity,
                                         ArrayList<EasyTransitionOptions.ViewAttrs> attrs,
                                         long duration,
                                         TimeInterpolator interpolator) {
        if (null == attrs || attrs.size() == 0)
            return;
 
        for (final EasyTransitionOptions.ViewAttrs attr : attrs) {
            View view = activity.findViewById(attr.id);
            int[] location = new int[2];
            view.getLocationOnScreen(location);
            view.setPivotX(0);
            view.setPivotY(0);
 
            view.animate()
                    .scaleX(attr.width / view.getWidth())
                    .scaleY(attr.height / view.getHeight())
                    .translationX(attr.startX - location[0])
                    .translationY(attr.startY - location[1])
                    .setInterpolator(interpolator)
                    .setDuration(duration);
        }
 
        activity.findViewById(attrs.get(0).id).postDelayed(new Runnable() {
            @Override
            public void run() {
                activity.finish();
                activity.overridePendingTransition(0, 0);
            }
        }, duration);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import android.app.Activity;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
 
import java.util.ArrayList;
 
/**
 * Transition options, using {@link EasyTransitionOptions#makeTransitionOptions(Activity, View...)}
 * to build your options
 * <br/>
 * Created by huzn on 2017/5/8.
 */
public class EasyTransitionOptions {
 
    private Activity activity;
    private View[] views;
    private ArrayList<ViewAttrs> attrs;
 
    public EasyTransitionOptions(Activity activity, View[] views) {
        this.activity = activity;
        this.views = views;
    }
 
    /**
     * Make options for transition
     *
     * @param activity The activity who contains shared views
     * @param views    Shared views, which must contains same id between two activities
     * @return A new transition options that will be used to build our transition animations
     */
    public static EasyTransitionOptions makeTransitionOptions(Activity activity, View... views) {
        return new EasyTransitionOptions(activity, views);
    }
 
    public void update() {
        if (null == views)
            return;
 
        attrs = new ArrayList<>();
        for (View v : views) {
            int[] location = new int[2];
            v.getLocationOnScreen(location);
            attrs.add(new ViewAttrs(
                    v.getId(),
                    location[0],
                    location[1],
                    v.getWidth(),
                    v.getHeight()
            ));
        }
    }
 
    public Activity getActivity() {
        return activity;
    }
 
    public ArrayList<ViewAttrs> getAttrs() {
        return attrs;
    }
 
    public static class ViewAttrs implements Parcelable {
        public int id;
        public float startX;
        public float startY;
        public float width;
        public float height;
 
        public ViewAttrs(int id, float startX, float startY, float width, float height) {
            this.id = id;
            this.startX = startX;
            this.startY = startY;
            this.width = width;
            this.height = height;
        }
 
        // Parcelable
        @Override
        public int describeContents() {
            return 0;
        }
 
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.id);
            dest.writeFloat(this.startX);
            dest.writeFloat(this.startY);
            dest.writeFloat(this.width);
            dest.writeFloat(this.height);
        }
 
        protected ViewAttrs(Parcel in) {
            this.id = in.readInt();
            this.startX = in.readFloat();
            this.startY = in.readFloat();
            this.width = in.readFloat();
            this.height = in.readFloat();
        }
 
        public static final Parcelable.Creator<ViewAttrs> CREATOR = new Parcelable.Creator<ViewAttrs>() {
            @Override
            public ViewAttrs createFromParcel(Parcel source) {
                return new ViewAttrs(source);
            }
 
            @Override
            public ViewAttrs[] newArray(int size) {
                return new ViewAttrs[size];
            }
        };
    }
}

 

 场景使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
 
import java.util.ArrayList;
 
public class MainActivity extends AppCompatActivity {
 
    private ArrayList<String> list;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add("name" + i);
        }
        ListView listView = (ListView) findViewById(R.id.lv);
        listView.setAdapter(new MyAdapter());
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // ready for intent
                Intent intent = new Intent(MainActivity.this, DetailActivity.class);
                intent.putExtra("name", list.get(position));
 
                // ready for transition options
                EasyTransitionOptions options =
                        EasyTransitionOptions.makeTransitionOptions(
                                MainActivity.this,
                                view.findViewById(R.id.iv_icon),
                                view.findViewById(R.id.tv_name),
                                findViewById(R.id.v_top_card));
 
                // start transition
                EasyTransition.startActivity(intent, options);
            }
        });
    }
 
 
    private class MyAdapter extends BaseAdapter {
 
        @Override
        public int getCount() {
            int count = 0;
            if (null != list)
                count = list.size();
            return count;
        }
 
        @Override
        public Object getItem(int position) {
            return list.get(position);
        }
 
        @Override
        public long getItemId(int position) {
            return position;
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = null;
            if (null != convertView) {
                view = convertView;
            } else {
                view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_main_list, null, false);
            }
            TextView tvName = (TextView) view.findViewById(R.id.tv_name);
            tvName.setText(list.get(position));
            return view;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
 
public class DetailActivity extends AppCompatActivity {
 
    private LinearLayout layoutAbout;
    private ImageView ivAdd;
    private boolean finishEnter;
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
 
        // pre init some views and data
        initViews();
 
        // if re-initialized, do not play any anim
        long transitionDuration = 800;
        if (null != savedInstanceState)
            transitionDuration = 0;
 
        // transition enter
        finishEnter = false;
        EasyTransition.enter(
                this,
                transitionDuration,
                new DecelerateInterpolator(),
                new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        // init other views after transition anim
                        finishEnter = true;
                        initOtherViews();
                    }
                });
    }
 
    private void initViews() {
        TextView tvName = (TextView) findViewById(R.id.tv_name);
        tvName.setText(getIntent().getStringExtra("name"));
    }
 
    private void initOtherViews() {
        layoutAbout = (LinearLayout) findViewById(R.id.layout_about);
        layoutAbout.setVisibility(View.VISIBLE);
        layoutAbout.setAlpha(0);
        layoutAbout.setTranslationY(-30);
        layoutAbout.animate()
                .setDuration(300)
                .alpha(1)
                .translationY(0);
 
        ivAdd = (ImageView) findViewById(R.id.iv_add);
        ivAdd.setVisibility(View.VISIBLE);
        ivAdd.setScaleX(0);
        ivAdd.setScaleY(0);
        ivAdd.animate()
                .setDuration(200)
                .scaleX(1)
                .scaleY(1);
    }
 
    @Override
    public void onBackPressed() {
        if (finishEnter) {
            finishEnter = false;
            startBackAnim();
        }
    }
 
    private void startBackAnim() {
        // forbidden scrolling
        ScrollView sv = (ScrollView) findViewById(R.id.sv);
        sv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
 
        // start our anim
        ivAdd.animate()
                .setDuration(200)
                .scaleX(0)
                .scaleY(0);
 
        layoutAbout.animate()
                .setDuration(300)
                .alpha(0)
                .translationY(-30)
                .setListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        // transition exit after our anim
                        EasyTransition.exit(DetailActivity.this, 800, new DecelerateInterpolator());
                    }
                });
    }
}

 activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    tools:context="com.hzn.easytransition.MainActivity"
    >
 
    <TextView
        android:id="@+id/title_bar"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:background="@color/colorPrimary"
        android:gravity="center_vertical"
        android:paddingLeft="16sp"
        android:text="TITLE"
        android:textColor="#ffffff"
        android:textSize="25sp"
        />
 
    <View
        android:id="@+id/v_top_card"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_below="@id/title_bar"
        android:background="@color/colorPrimary"
        />
 
    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/title_bar"
        />
</RelativeLayout>

 

activity_detail.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    tools:context="com.hzn.easytransition.MainActivity"
    >
 
    <TextView
        android:id="@+id/title_bar"
        android:layout_width="match_parent"
        android:layout_height="55dp"
        android:background="@color/colorPrimary"
        android:gravity="center_vertical"
        android:paddingLeft="16sp"
        android:text="TITLE"
        android:textColor="#ffffff"
        android:textSize="25sp"
        />
 
    <View
        android:id="@+id/v_top_card"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:layout_below="@+id/title_bar"
        android:background="@color/colorPrimary"
        />
 
    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:src="@mipmap/avatar_male"
        />
 
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/iv_icon"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="10dp"
        android:textColor="#5b5b5b"
        android:textSize="50sp"
        />
 
    <ScrollView
        android:id="@+id/sv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/tv_name"
        android:overScrollMode="never"
        android:scrollbars="none"
        >
 
        <LinearLayout
            android:id="@+id/layout_about"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:orientation="vertical"
            android:paddingBottom="40dp"
            android:paddingTop="20dp"
            android:visibility="invisible"
            >
 
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/icon_phone"
                android:drawablePadding="10dp"
                android:gravity="center_vertical"
                android:text="151-2121-2121"
                android:textColor="#446880"
                android:textSize="16sp"
                />
 
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:drawableLeft="@mipmap/icon_email"
                android:drawablePadding="10dp"
                android:gravity="center_vertical"
                android:text="243666666@gmail.com"
                android:textColor="#446880"
                android:textSize="16sp"
                />
 
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:drawableLeft="@mipmap/icon_location"
                android:drawablePadding="10dp"
                android:gravity="center_vertical"
                android:text="China, Guangdong, Shenzhen"
                android:textColor="#446880"
                android:textSize="16sp"
                />
        </LinearLayout>
    </ScrollView>
 
    <ImageView
        android:id="@+id/iv_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:padding="16dp"
        android:src="@mipmap/icon_add"
        android:visibility="gone"
        />
</RelativeLayout>

item_main_list.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:padding="16dp"
    >
 
    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@mipmap/avatar_male"
        />
 
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_toRightOf="@+id/iv_icon"
        android:text="name"
        android:textColor="#5b5b5b"
        android:textSize="20sp"
        />
 
</RelativeLayout>

 效果图:


 

学习来源:http://blog.csdn.net/u012199331/article/details/72137112


 

 

 

 

 

 

 

posted on   LoaderMan  阅读(1157)  评论(0)    收藏  举报

< 2025年4月 >
30 31 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 1 2 3
4 5 6 7 8 9 10

导航

统计

喜欢请打赏

扫描二维码打赏

了解更多

点击右上角即可分享
微信分享提示