zkit-ui 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/android/build.gradle +100 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewLayoutSupport.java +450 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewMediaItem.java +36 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewModule.kt +43 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewPagerAdapter.java +140 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementGeometry.java +25 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementNames.java +39 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementState.java +25 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSourceViewRegistry.java +115 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewTransitionSnapshotView.java +60 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewVideoPlayerView.java +338 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewView.kt +305 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewViewerOverlayView.java +636 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewViewerPageView.java +357 -0
- package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewViewerTransitionController.java +223 -0
- package/android/src/main/res/layout/native_image_preview_player_view.xml +9 -0
- package/dist/all.d.ts +2 -0
- package/dist/all.d.ts.map +1 -1
- package/dist/all.js +24 -22
- package/dist/ui/NativeImagePreview/NativeImagePreview.d.ts +3 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.js +99 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.d.ts +4 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/NativeImagePreview.web.js +150 -0
- package/dist/ui/NativeImagePreview/context.d.ts +14 -0
- package/dist/ui/NativeImagePreview/context.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/context.js +38 -0
- package/dist/ui/NativeImagePreview/index.d.ts +3 -0
- package/dist/ui/NativeImagePreview/index.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/index.js +5 -0
- package/dist/ui/NativeImagePreview/types.d.ts +68 -0
- package/dist/ui/NativeImagePreview/types.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/types.js +2 -0
- package/dist/ui/NativeImagePreview/utils.d.ts +8 -0
- package/dist/ui/NativeImagePreview/utils.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/utils.js +83 -0
- package/dist/ui/NativeImagePreview/web/geometry.d.ts +20 -0
- package/dist/ui/NativeImagePreview/web/geometry.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/geometry.js +121 -0
- package/dist/ui/NativeImagePreview/web/media.d.ts +6 -0
- package/dist/ui/NativeImagePreview/web/media.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/media.js +90 -0
- package/dist/ui/NativeImagePreview/web/styles.css +137 -0
- package/dist/ui/NativeImagePreview/web/transition.d.ts +15 -0
- package/dist/ui/NativeImagePreview/web/transition.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/transition.js +77 -0
- package/dist/ui/NativeImagePreview/web/types.d.ts +74 -0
- package/dist/ui/NativeImagePreview/web/types.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/types.js +3 -0
- package/dist/ui/NativeImagePreview/web/viewer.d.ts +104 -0
- package/dist/ui/NativeImagePreview/web/viewer.d.ts.map +1 -0
- package/dist/ui/NativeImagePreview/web/viewer.js +894 -0
- package/expo-module.config.json +11 -0
- package/ios/NativeImagePreview/NativeImagePreviewImageLoader.swift +73 -0
- package/ios/NativeImagePreview/NativeImagePreviewImageViewInteraction.swift +245 -0
- package/ios/NativeImagePreview/NativeImagePreviewLayoutSupport.swift +143 -0
- package/ios/NativeImagePreview/NativeImagePreviewMedia.swift +28 -0
- package/ios/NativeImagePreview/NativeImagePreviewSourceViewRegistry.swift +80 -0
- package/ios/NativeImagePreview/NativeImagePreviewVideoPlayerView.swift +437 -0
- package/ios/NativeImagePreview/NativeImagePreviewViewerConfiguration.swift +51 -0
- package/ios/NativeImagePreview/NativeImagePreviewViewerController.swift +745 -0
- package/ios/NativeImagePreview/NativeImagePreviewViewerPageView.swift +623 -0
- package/ios/NativeImagePreview/NativeImagePreviewViewerTransitionCoordinator.swift +312 -0
- package/ios/NativeImagePreviewModule.swift +46 -0
- package/ios/NativeImagePreviewView.swift +252 -0
- package/package.json +16 -2
- package/src/all.ts +18 -0
- package/src/services/ImagePreviewService/README.md +19 -0
- package/src/types.d.ts +1 -0
- package/src/ui/NativeImagePreview/NativeImagePreview.tsx +146 -0
- package/src/ui/NativeImagePreview/NativeImagePreview.web.tsx +201 -0
- package/src/ui/NativeImagePreview/README.md +111 -0
- package/src/ui/NativeImagePreview/context.tsx +22 -0
- package/src/ui/NativeImagePreview/index.tsx +18 -0
- package/src/ui/NativeImagePreview/types.ts +94 -0
- package/src/ui/NativeImagePreview/utils.ts +108 -0
- package/src/ui/NativeImagePreview/web/geometry.ts +134 -0
- package/src/ui/NativeImagePreview/web/media.ts +91 -0
- package/src/ui/NativeImagePreview/web/styles.css +137 -0
- package/src/ui/NativeImagePreview/web/transition.ts +111 -0
- package/src/ui/NativeImagePreview/web/types.ts +88 -0
- package/src/ui/NativeImagePreview/web/viewer.ts +1024 -0
- package/zkit-ui.podspec +13 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.modules.Module
|
|
4
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
5
|
+
|
|
6
|
+
class NativeImagePreviewModule : Module() {
|
|
7
|
+
override fun definition() = ModuleDefinition {
|
|
8
|
+
Name("ZKitNativeImagePreview")
|
|
9
|
+
|
|
10
|
+
View(NativeImagePreviewView::class) {
|
|
11
|
+
Events(
|
|
12
|
+
"onIndexChange"
|
|
13
|
+
)
|
|
14
|
+
Prop("theme") { view: NativeImagePreviewView, theme: Theme ->
|
|
15
|
+
view.theme = theme
|
|
16
|
+
}
|
|
17
|
+
Prop("items") { view: NativeImagePreviewView, items: Array<Map<String, Any?>> ->
|
|
18
|
+
view.items = items.toList()
|
|
19
|
+
}
|
|
20
|
+
Prop("urls") { view: NativeImagePreviewView, urls: Array<String> ->
|
|
21
|
+
view.urls = urls
|
|
22
|
+
}
|
|
23
|
+
Prop("index") { view: NativeImagePreviewView, index: Int ->
|
|
24
|
+
view.initialIndex = index
|
|
25
|
+
}
|
|
26
|
+
Prop("previewGroupId") { view: NativeImagePreviewView, previewGroupId: String? ->
|
|
27
|
+
view.previewGroupId = previewGroupId
|
|
28
|
+
}
|
|
29
|
+
Prop("disableHiddenOriginalImage") { view: NativeImagePreviewView, disableHiddenOriginalImage: Boolean ->
|
|
30
|
+
view.disableHiddenOriginalImage = disableHiddenOriginalImage
|
|
31
|
+
}
|
|
32
|
+
Prop("edgeToEdge") { view: NativeImagePreviewView, edgeToEdge: Boolean ->
|
|
33
|
+
view.edgeToEdge = edgeToEdge
|
|
34
|
+
}
|
|
35
|
+
Prop("transitionOffsetY") { view: NativeImagePreviewView, transitionOffsetY: Int? ->
|
|
36
|
+
view.transitionOffsetY = transitionOffsetY
|
|
37
|
+
}
|
|
38
|
+
Prop("transitionOffsetX") { view: NativeImagePreviewView, transitionOffsetX: Int? ->
|
|
39
|
+
view.transitionOffsetX = transitionOffsetX
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import android.view.ViewGroup;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
import androidx.recyclerview.widget.RecyclerView;
|
|
8
|
+
|
|
9
|
+
import java.util.ArrayList;
|
|
10
|
+
import java.util.HashMap;
|
|
11
|
+
import java.util.List;
|
|
12
|
+
import java.util.Map;
|
|
13
|
+
|
|
14
|
+
public final class NativeImagePreviewPagerAdapter extends RecyclerView.Adapter<NativeImagePreviewPagerAdapter.PageViewHolder> {
|
|
15
|
+
public interface PageBindCallback {
|
|
16
|
+
void onPageBound(@NonNull NativeImagePreviewViewerPageView pageView, int position);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
private final List<NativeImagePreviewMediaItem> items = new ArrayList<>();
|
|
20
|
+
private final Map<Integer, NativeImagePreviewViewerPageView> attachedViews = new HashMap<>();
|
|
21
|
+
@Nullable
|
|
22
|
+
private final NativeImagePreviewViewerPageView.Listener pageListener;
|
|
23
|
+
@Nullable
|
|
24
|
+
private final PageBindCallback pageBindCallback;
|
|
25
|
+
private int activeIndex = -1;
|
|
26
|
+
|
|
27
|
+
public NativeImagePreviewPagerAdapter(
|
|
28
|
+
@Nullable NativeImagePreviewViewerPageView.Listener pageListener,
|
|
29
|
+
@Nullable PageBindCallback pageBindCallback
|
|
30
|
+
) {
|
|
31
|
+
this.pageListener = pageListener;
|
|
32
|
+
this.pageBindCallback = pageBindCallback;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public void setItems(@NonNull List<NativeImagePreviewMediaItem> list) {
|
|
36
|
+
attachedViews.clear();
|
|
37
|
+
items.clear();
|
|
38
|
+
items.addAll(list);
|
|
39
|
+
notifyDataSetChanged();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public void setActiveIndex(int index) {
|
|
43
|
+
activeIndex = index;
|
|
44
|
+
for (Map.Entry<Integer, NativeImagePreviewViewerPageView> entry : attachedViews.entrySet()) {
|
|
45
|
+
entry.getValue().setActive(entry.getKey() == index);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public void releaseAll() {
|
|
50
|
+
for (NativeImagePreviewViewerPageView view : attachedViews.values()) {
|
|
51
|
+
view.release();
|
|
52
|
+
}
|
|
53
|
+
attachedViews.clear();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Nullable
|
|
57
|
+
public NativeImagePreviewViewerPageView findAttachedView(int position) {
|
|
58
|
+
NativeImagePreviewViewerPageView pageView = attachedViews.get(position);
|
|
59
|
+
if (pageView == null) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (!pageView.isAttachedToWindow()) {
|
|
63
|
+
attachedViews.remove(position);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return pageView;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@Nullable
|
|
70
|
+
public NativeImagePreviewViewerPageView findActiveView() {
|
|
71
|
+
return attachedViews.get(activeIndex);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@NonNull
|
|
75
|
+
@Override
|
|
76
|
+
public PageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
77
|
+
NativeImagePreviewViewerPageView pageView = new NativeImagePreviewViewerPageView(parent.getContext());
|
|
78
|
+
pageView.setListener(pageListener);
|
|
79
|
+
return new PageViewHolder(pageView);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@Override
|
|
83
|
+
public void onBindViewHolder(@NonNull PageViewHolder holder, int position) {
|
|
84
|
+
holder.pageView.bind(items.get(position));
|
|
85
|
+
if (pageBindCallback != null) {
|
|
86
|
+
pageBindCallback.onPageBound(holder.pageView, position);
|
|
87
|
+
}
|
|
88
|
+
holder.pageView.setActive(position == activeIndex);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@Override
|
|
92
|
+
public void onViewAttachedToWindow(@NonNull PageViewHolder holder) {
|
|
93
|
+
super.onViewAttachedToWindow(holder);
|
|
94
|
+
removeAttachedViewKeys(holder.pageView);
|
|
95
|
+
int position = holder.getBindingAdapterPosition();
|
|
96
|
+
if (position == RecyclerView.NO_POSITION) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
attachedViews.put(position, holder.pageView);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@Override
|
|
103
|
+
public void onViewDetachedFromWindow(@NonNull PageViewHolder holder) {
|
|
104
|
+
super.onViewDetachedFromWindow(holder);
|
|
105
|
+
removeAttachedViewKeys(holder.pageView);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Override
|
|
109
|
+
public void onViewRecycled(@NonNull PageViewHolder holder) {
|
|
110
|
+
super.onViewRecycled(holder);
|
|
111
|
+
removeAttachedViewKeys(holder.pageView);
|
|
112
|
+
holder.pageView.release();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private void removeAttachedViewKeys(@NonNull NativeImagePreviewViewerPageView pageView) {
|
|
116
|
+
List<Integer> keys = new ArrayList<>();
|
|
117
|
+
for (Map.Entry<Integer, NativeImagePreviewViewerPageView> entry : attachedViews.entrySet()) {
|
|
118
|
+
if (entry.getValue() == pageView) {
|
|
119
|
+
keys.add(entry.getKey());
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (Integer key : keys) {
|
|
123
|
+
attachedViews.remove(key);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Override
|
|
128
|
+
public int getItemCount() {
|
|
129
|
+
return items.size();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static final class PageViewHolder extends RecyclerView.ViewHolder {
|
|
133
|
+
final NativeImagePreviewViewerPageView pageView;
|
|
134
|
+
|
|
135
|
+
PageViewHolder(@NonNull NativeImagePreviewViewerPageView itemView) {
|
|
136
|
+
super(itemView);
|
|
137
|
+
this.pageView = itemView;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import android.graphics.RectF;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
public final class NativeImagePreviewSharedElementGeometry {
|
|
8
|
+
private final RectF visibleFrameInWindow;
|
|
9
|
+
private final RectF contentFrameInVisibleBounds;
|
|
10
|
+
|
|
11
|
+
public NativeImagePreviewSharedElementGeometry(@NonNull RectF visibleFrameInWindow, @NonNull RectF contentFrameInVisibleBounds) {
|
|
12
|
+
this.visibleFrameInWindow = new RectF(visibleFrameInWindow);
|
|
13
|
+
this.contentFrameInVisibleBounds = new RectF(contentFrameInVisibleBounds);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@NonNull
|
|
17
|
+
public RectF getVisibleFrameInWindow() {
|
|
18
|
+
return new RectF(visibleFrameInWindow);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@NonNull
|
|
22
|
+
public RectF getContentFrameInVisibleBounds() {
|
|
23
|
+
return new RectF(contentFrameInVisibleBounds);
|
|
24
|
+
}
|
|
25
|
+
}
|
package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementNames.java
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
4
|
+
import androidx.annotation.Nullable;
|
|
5
|
+
|
|
6
|
+
public final class NativeImagePreviewSharedElementNames {
|
|
7
|
+
private static final String PREFIX = "zkit-native-image-preview:media:";
|
|
8
|
+
|
|
9
|
+
private NativeImagePreviewSharedElementNames() {
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@NonNull
|
|
13
|
+
public static String forItem(@NonNull NativeImagePreviewMediaItem item) {
|
|
14
|
+
return forItem(null, item);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@NonNull
|
|
18
|
+
public static String forItem(@Nullable String previewGroupId, @NonNull NativeImagePreviewMediaItem item) {
|
|
19
|
+
return forId(previewGroupId, item.getId());
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@NonNull
|
|
23
|
+
public static String forIndex(int index) {
|
|
24
|
+
return forIndex(null, index);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@NonNull
|
|
28
|
+
public static String forIndex(@Nullable String previewGroupId, int index) {
|
|
29
|
+
return forId(previewGroupId, String.valueOf(index));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@NonNull
|
|
33
|
+
private static String forId(@Nullable String previewGroupId, @NonNull String id) {
|
|
34
|
+
if (previewGroupId == null || previewGroupId.isEmpty()) {
|
|
35
|
+
return PREFIX + id;
|
|
36
|
+
}
|
|
37
|
+
return PREFIX + previewGroupId + ":" + id;
|
|
38
|
+
}
|
|
39
|
+
}
|
package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSharedElementState.java
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import android.graphics.drawable.Drawable;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
|
|
7
|
+
public final class NativeImagePreviewSharedElementState {
|
|
8
|
+
private final Drawable drawable;
|
|
9
|
+
private final NativeImagePreviewSharedElementGeometry geometry;
|
|
10
|
+
|
|
11
|
+
public NativeImagePreviewSharedElementState(@NonNull Drawable drawable, @NonNull NativeImagePreviewSharedElementGeometry geometry) {
|
|
12
|
+
this.drawable = drawable;
|
|
13
|
+
this.geometry = geometry;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@NonNull
|
|
17
|
+
public Drawable getDrawable() {
|
|
18
|
+
return drawable;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@NonNull
|
|
22
|
+
public NativeImagePreviewSharedElementGeometry getGeometry() {
|
|
23
|
+
return geometry;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/android/src/main/java/cn/fontree/zkit/ui/preview/NativeImagePreviewSourceViewRegistry.java
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import android.view.View;
|
|
4
|
+
import android.widget.ImageView;
|
|
5
|
+
|
|
6
|
+
import androidx.annotation.NonNull;
|
|
7
|
+
import androidx.annotation.Nullable;
|
|
8
|
+
import androidx.core.view.ViewCompat;
|
|
9
|
+
|
|
10
|
+
import java.lang.ref.WeakReference;
|
|
11
|
+
import java.util.HashMap;
|
|
12
|
+
import java.util.Iterator;
|
|
13
|
+
import java.util.Map;
|
|
14
|
+
|
|
15
|
+
public final class NativeImagePreviewSourceViewRegistry {
|
|
16
|
+
private static final Map<String, WeakReference<ImageView>> SOURCE_VIEWS = new HashMap<>();
|
|
17
|
+
|
|
18
|
+
private NativeImagePreviewSourceViewRegistry() {
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public static synchronized void register(@NonNull String key, @NonNull ImageView imageView) {
|
|
22
|
+
cleanupLocked();
|
|
23
|
+
if (!hasUsableGeometry(imageView)) {
|
|
24
|
+
ImageView existingImageView = resolveMappedViewLocked(key);
|
|
25
|
+
boolean keepExisting = existingImageView != null
|
|
26
|
+
&& existingImageView != imageView
|
|
27
|
+
&& hasUsableGeometry(existingImageView);
|
|
28
|
+
clearMappingsForViewLocked(imageView);
|
|
29
|
+
if (keepExisting) {
|
|
30
|
+
SOURCE_VIEWS.put(key, new WeakReference<>(existingImageView));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
SOURCE_VIEWS.remove(key);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
ImageView previousImageView = resolveMappedViewLocked(key);
|
|
38
|
+
if (!isPreferredSourceView(imageView)
|
|
39
|
+
&& previousImageView != null
|
|
40
|
+
&& previousImageView != imageView
|
|
41
|
+
&& isPreferredSourceView(previousImageView)) {
|
|
42
|
+
clearMappingsForViewLocked(imageView);
|
|
43
|
+
SOURCE_VIEWS.put(key, new WeakReference<>(previousImageView));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
clearMappingsForViewLocked(imageView);
|
|
48
|
+
SOURCE_VIEWS.put(key, new WeakReference<>(imageView));
|
|
49
|
+
ViewCompat.setTransitionName(imageView, key);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public static synchronized void unregisterView(@NonNull ImageView imageView) {
|
|
53
|
+
clearMappingsForViewLocked(imageView);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Nullable
|
|
57
|
+
public static synchronized ImageView find(@NonNull String key) {
|
|
58
|
+
cleanupLocked();
|
|
59
|
+
WeakReference<ImageView> reference = SOURCE_VIEWS.get(key);
|
|
60
|
+
if (reference == null) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
ImageView imageView = reference.get();
|
|
64
|
+
if (imageView == null || !imageView.isAttachedToWindow()) {
|
|
65
|
+
SOURCE_VIEWS.remove(key);
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
if (!hasUsableGeometry(imageView)) {
|
|
69
|
+
SOURCE_VIEWS.remove(key);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return imageView;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@Nullable
|
|
76
|
+
private static ImageView resolveMappedViewLocked(@NonNull String key) {
|
|
77
|
+
WeakReference<ImageView> reference = SOURCE_VIEWS.get(key);
|
|
78
|
+
return reference != null ? reference.get() : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private static boolean hasUsableGeometry(@Nullable ImageView imageView) {
|
|
82
|
+
return imageView != null
|
|
83
|
+
&& imageView.isAttachedToWindow()
|
|
84
|
+
&& imageView.getWidth() > 0
|
|
85
|
+
&& imageView.getHeight() > 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private static boolean isPreferredSourceView(@Nullable ImageView imageView) {
|
|
89
|
+
return hasUsableGeometry(imageView)
|
|
90
|
+
&& imageView.getVisibility() == View.VISIBLE
|
|
91
|
+
&& imageView.isShown();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private static void clearMappingsForViewLocked(@NonNull ImageView imageView) {
|
|
95
|
+
Iterator<Map.Entry<String, WeakReference<ImageView>>> iterator = SOURCE_VIEWS.entrySet().iterator();
|
|
96
|
+
while (iterator.hasNext()) {
|
|
97
|
+
Map.Entry<String, WeakReference<ImageView>> entry = iterator.next();
|
|
98
|
+
ImageView mappedView = entry.getValue().get();
|
|
99
|
+
if (mappedView == null || mappedView == imageView) {
|
|
100
|
+
iterator.remove();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private static void cleanupLocked() {
|
|
106
|
+
Iterator<Map.Entry<String, WeakReference<ImageView>>> iterator = SOURCE_VIEWS.entrySet().iterator();
|
|
107
|
+
while (iterator.hasNext()) {
|
|
108
|
+
Map.Entry<String, WeakReference<ImageView>> entry = iterator.next();
|
|
109
|
+
ImageView mappedView = entry.getValue().get();
|
|
110
|
+
if (mappedView == null) {
|
|
111
|
+
iterator.remove();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package cn.fontree.zkit.ui.preview;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.graphics.RectF;
|
|
5
|
+
import android.graphics.drawable.Drawable;
|
|
6
|
+
import android.view.Gravity;
|
|
7
|
+
import android.widget.FrameLayout;
|
|
8
|
+
import android.widget.ImageView;
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.NonNull;
|
|
11
|
+
|
|
12
|
+
public final class NativeImagePreviewTransitionSnapshotView extends FrameLayout {
|
|
13
|
+
private final ImageView imageView;
|
|
14
|
+
|
|
15
|
+
public NativeImagePreviewTransitionSnapshotView(@NonNull Context context, @NonNull Drawable drawable) {
|
|
16
|
+
super(context);
|
|
17
|
+
setClipChildren(true);
|
|
18
|
+
setClipToPadding(true);
|
|
19
|
+
imageView = new ImageView(context);
|
|
20
|
+
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
|
21
|
+
imageView.setImageDrawable(drawable);
|
|
22
|
+
addView(imageView);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public void applyGeometry(@NonNull NativeImagePreviewSharedElementGeometry geometry) {
|
|
26
|
+
RectF visibleFrame = geometry.getVisibleFrameInWindow();
|
|
27
|
+
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) getLayoutParams();
|
|
28
|
+
if (layoutParams == null) {
|
|
29
|
+
layoutParams = new FrameLayout.LayoutParams(
|
|
30
|
+
Math.max(1, Math.round(visibleFrame.width())),
|
|
31
|
+
Math.max(1, Math.round(visibleFrame.height()))
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
layoutParams.width = Math.max(1, Math.round(visibleFrame.width()));
|
|
35
|
+
layoutParams.height = Math.max(1, Math.round(visibleFrame.height()));
|
|
36
|
+
layoutParams.leftMargin = 0;
|
|
37
|
+
layoutParams.topMargin = 0;
|
|
38
|
+
layoutParams.gravity = Gravity.TOP | Gravity.START;
|
|
39
|
+
setLayoutParams(layoutParams);
|
|
40
|
+
setX(visibleFrame.left);
|
|
41
|
+
setY(visibleFrame.top);
|
|
42
|
+
|
|
43
|
+
RectF contentFrame = geometry.getContentFrameInVisibleBounds();
|
|
44
|
+
FrameLayout.LayoutParams imageLayoutParams = (FrameLayout.LayoutParams) imageView.getLayoutParams();
|
|
45
|
+
if (imageLayoutParams == null) {
|
|
46
|
+
imageLayoutParams = new FrameLayout.LayoutParams(
|
|
47
|
+
Math.max(1, Math.round(contentFrame.width())),
|
|
48
|
+
Math.max(1, Math.round(contentFrame.height()))
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
imageLayoutParams.width = Math.max(1, Math.round(contentFrame.width()));
|
|
52
|
+
imageLayoutParams.height = Math.max(1, Math.round(contentFrame.height()));
|
|
53
|
+
imageLayoutParams.leftMargin = 0;
|
|
54
|
+
imageLayoutParams.topMargin = 0;
|
|
55
|
+
imageLayoutParams.gravity = Gravity.TOP | Gravity.START;
|
|
56
|
+
imageView.setLayoutParams(imageLayoutParams);
|
|
57
|
+
imageView.setX(contentFrame.left);
|
|
58
|
+
imageView.setY(contentFrame.top);
|
|
59
|
+
}
|
|
60
|
+
}
|