PickerLayoutManager.java
8.47 KB
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
package com.studymachine.www.manager;
import android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
/**
* author : 钉某人 & Android 轮子哥
* github : https://github.com/DingMouRen/LayoutManagerGroup
*/
public final class PickerLayoutManager extends LinearLayoutManager {
private final LinearSnapHelper mLinearSnapHelper;
private final int mOrientation;
private final int mMaxItem;
private final float mScale;
private final boolean mAlpha;
private RecyclerView mRecyclerView;
@Nullable
private OnPickerListener mListener;
private PickerLayoutManager(Context context, int orientation, boolean reverseLayout, int maxItem, float scale, boolean alpha) {
super(context, orientation, reverseLayout);
mLinearSnapHelper = new LinearSnapHelper();
mMaxItem = maxItem;
mOrientation = orientation;
mAlpha = alpha;
mScale = scale;
}
@Override
public void onAttachedToWindow(RecyclerView recyclerView) {
super.onAttachedToWindow(recyclerView);
mRecyclerView = recyclerView;
// 设置子控件的边界可以超过父布局的范围
mRecyclerView.setClipToPadding(false);
// 添加 LinearSnapHelper
mLinearSnapHelper.attachToRecyclerView(mRecyclerView);
}
@Override
public void onDetachedFromWindow(RecyclerView recyclerView, RecyclerView.Recycler recycler) {
super.onDetachedFromWindow(recyclerView, recycler);
mRecyclerView = null;
}
@Override
public boolean isAutoMeasureEnabled() {
return mMaxItem == 0;
}
@Override
public void onMeasure(@NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state, int widthSpec, int heightSpec) {
int width = RecyclerView.LayoutManager.chooseSize(widthSpec,
getPaddingLeft() + getPaddingRight(),
ViewCompat.getMinimumWidth(mRecyclerView));
int height = RecyclerView.LayoutManager.chooseSize(heightSpec,
getPaddingTop() + getPaddingBottom(),
ViewCompat.getMinimumHeight(mRecyclerView));
if (state.getItemCount() != 0 && mMaxItem != 0) {
View itemView = recycler.getViewForPosition(0);
measureChildWithMargins(itemView, widthSpec, heightSpec);
if (mOrientation == HORIZONTAL) {
int measuredWidth = itemView.getMeasuredWidth();
int paddingHorizontal = (mMaxItem - 1) / 2 * measuredWidth;
mRecyclerView.setPadding(paddingHorizontal,0, paddingHorizontal,0);
width = measuredWidth * mMaxItem;
} else if (mOrientation == VERTICAL) {
int measuredHeight = itemView.getMeasuredHeight();
int paddingVertical = (mMaxItem - 1) / 2 * measuredHeight;
mRecyclerView.setPadding(0, paddingVertical,0, paddingVertical);
height = measuredHeight * mMaxItem;
}
}
setMeasuredDimension(width, height);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
// 当 RecyclerView 停止滚动时
if (state != RecyclerView.SCROLL_STATE_IDLE) {
return;
}
if (mListener == null) {
return;
}
mListener.onPicked(mRecyclerView, getPickedPosition());
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
if (getItemCount() < 0 || state.isPreLayout()) {
return;
}
if (mOrientation == HORIZONTAL) {
scaleHorizontalChildView();
} else if (mOrientation == VERTICAL) {
scaleVerticalChildView();
}
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
scaleHorizontalChildView();
return super.scrollHorizontallyBy(dx, recycler, state);
}
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
scaleVerticalChildView();
return super.scrollVerticallyBy(dy, recycler, state);
}
/**
* 横向情况下的缩放
*/
private void scaleHorizontalChildView() {
float mid = getWidth() / 2.0f;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
if (childView == null) {
continue;
}
float childMid = (getDecoratedLeft(childView) + getDecoratedRight(childView)) / 2.0f;
float scale = 1.0f + (-1 * (1 - mScale)) * (Math.min(mid, Math.abs(mid - childMid))) / mid;
childView.setScaleX(scale);
childView.setScaleY(scale);
if (mAlpha) {
childView.setAlpha(scale);
}
}
}
/**
* 竖向方向上的缩放
*/
private void scaleVerticalChildView() {
float mid = getHeight() / 2.0f;
for (int i = 0; i < getChildCount(); i++) {
View childView = getChildAt(i);
if (childView == null) {
continue;
}
float childMid = (getDecoratedTop(childView) + getDecoratedBottom(childView)) / 2.0f;
float scale = 1.0f + (-1 * (1 - mScale)) * (Math.min(mid, Math.abs(mid - childMid))) / mid;
childView.setScaleX(scale);
childView.setScaleY(scale);
if (mAlpha) {
childView.setAlpha(scale);
}
}
}
/**
* 获取选中的位置
*/
public int getPickedPosition() {
View itemView = mLinearSnapHelper.findSnapView(this);
if(itemView == null) {
return 0;
}
return getPosition(itemView);
}
/**
* 设置监听器
*/
public void setOnPickerListener(@Nullable OnPickerListener listener) {
mListener = listener;
}
public interface OnPickerListener {
/**
* 滚动停止时触发的监听
*
* @param recyclerView RecyclerView 对象
* @param position 当前滚动的位置
*/
void onPicked(RecyclerView recyclerView, int position);
}
public static final class Builder {
private final Context mContext;
private int mOrientation = VERTICAL;
private boolean mReverseLayout;
private OnPickerListener mListener;
private int mMaxItem = 3;
private float mScale = 0.6f;
private boolean mAlpha = true;
public Builder(Context context) {
mContext = context;
}
/**
* 设置布局摆放器方向
*/
public Builder setOrientation(@RecyclerView.Orientation int orientation) {
mOrientation = orientation;
return this;
}
/**
* 设置是否反向显示
*/
public Builder setReverseLayout(boolean reverseLayout) {
mReverseLayout = reverseLayout;
return this;
}
/**
* 设置最大显示条目数
*/
public Builder setMaxItem(int maxItem) {
mMaxItem = maxItem;
return this;
}
/**
* 设置缩放比例
*/
public Builder setScale(float scale) {
mScale = scale;
return this;
}
/**
* 设置透明开关
*/
public Builder setAlpha(boolean alpha) {
mAlpha = alpha;
return this;
}
public Builder setOnPickerListener(OnPickerListener listener) {
mListener = listener;
return this;
}
/**
* 构建布局管理器
*/
public PickerLayoutManager build() {
PickerLayoutManager layoutManager = new PickerLayoutManager(mContext, mOrientation, mReverseLayout, mMaxItem, mScale, mAlpha);
layoutManager.setOnPickerListener(mListener);
return layoutManager;
}
/**
* 应用到 RecyclerView
*/
public void into(RecyclerView recyclerView) {
recyclerView.setLayoutManager(build());
}
}
}