Android: implement slider style gallery
This commit is contained in:
parent
1d7001e01a
commit
bab16ddf27
@ -20,16 +20,18 @@ import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSArray;
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSNull;
|
||||
import com.github.pengfeizhou.jscore.JSObject;
|
||||
import com.github.pengfeizhou.jscore.JSValue;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.shader.ViewNode;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.shader.slider
|
||||
@ -46,6 +48,8 @@ class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.DoricViewHolder> {
|
||||
String renderPageFuncId;
|
||||
boolean loop;
|
||||
|
||||
float itemWidth;
|
||||
|
||||
SlideAdapter(SliderNode sliderNode) {
|
||||
this.sliderNode = sliderNode;
|
||||
}
|
||||
@ -71,6 +75,10 @@ class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.DoricViewHolder> {
|
||||
} catch (Exception e) {
|
||||
sliderNode.getDoricContext().getDriver().getRegistry().onException(sliderNode.getDoricContext(), e);
|
||||
}
|
||||
|
||||
if (sliderNode.slideStyle.equals("gallery")) {
|
||||
holder.itemView.getLayoutParams().width = DoricUtils.dp2px(this.itemWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,6 +157,10 @@ class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.DoricViewHolder> {
|
||||
}
|
||||
}
|
||||
|
||||
void setItemWidth(float itemWidth) {
|
||||
this.itemWidth = itemWidth;
|
||||
}
|
||||
|
||||
static class DoricViewHolder extends RecyclerView.ViewHolder {
|
||||
SlideItemNode slideItemNode;
|
||||
|
||||
|
@ -0,0 +1,97 @@
|
||||
package pub.doric.shader.slider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
public class SliderLayoutManager extends LinearLayoutManager {
|
||||
|
||||
private boolean enableGallery;
|
||||
private float minScale = 1f;
|
||||
private float itemWidth = 0;
|
||||
|
||||
private float minAlpha = 1f;
|
||||
|
||||
public SliderLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||
super(context, orientation, reverseLayout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
|
||||
if (enableGallery) {
|
||||
handleHorizontalView();
|
||||
}
|
||||
return super.scrollHorizontallyBy(dx, recycler, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLayoutCompleted(RecyclerView.State state) {
|
||||
super.onLayoutCompleted(state);
|
||||
|
||||
//scroll won't be called when first layout completed, so need to handle view at first time
|
||||
if (enableGallery) {
|
||||
handleView();
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnableGallery(boolean enableGallery) {
|
||||
this.enableGallery = enableGallery;
|
||||
}
|
||||
|
||||
public void setItemWidth(float itemWidth) {
|
||||
this.itemWidth = itemWidth;
|
||||
}
|
||||
|
||||
public void setMinScale(float minScale) {
|
||||
this.minScale = minScale;
|
||||
}
|
||||
|
||||
public void setMinAlpha(float minAlpha) {
|
||||
this.minAlpha = minAlpha;
|
||||
}
|
||||
|
||||
private void handleView() {
|
||||
if (getOrientation() == LinearLayoutManager.HORIZONTAL) {
|
||||
handleHorizontalView();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleHorizontalView() {
|
||||
float centerViewLeft = (float) (getWidth() - DoricUtils.dp2px(this.itemWidth)) / 2;//the left when the view is centered
|
||||
float moveX = DoricUtils.dp2px(this.itemWidth);//movement x from one item to another
|
||||
calculateScale(centerViewLeft, moveX);
|
||||
}
|
||||
|
||||
private void calculateScale(float centerViewLeft, float moveDistance) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
assert child != null;
|
||||
int left = child.getLeft();
|
||||
if (getOrientation() == LinearLayoutManager.VERTICAL) {
|
||||
left = child.getTop();
|
||||
}
|
||||
float factor = (left - centerViewLeft) / moveDistance;
|
||||
factor = Math.max(-1f, factor);
|
||||
factor = Math.min(1f, factor);
|
||||
if (factor > 0) {
|
||||
// right view to center
|
||||
scaleAndAlpha(child, 1f - factor * (1 - minScale), 1 - factor * (1 - minAlpha));
|
||||
} else {
|
||||
// left view to center
|
||||
scaleAndAlpha(child, 1f + factor * (1 - minScale), 1 + factor * (1 - minAlpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void scaleAndAlpha(View view, float scale, float alpha) {
|
||||
view.setPivotX(view.getWidth() / 2f);
|
||||
view.setPivotY(view.getHeight() / 2f);
|
||||
view.setScaleX(scale);
|
||||
view.setScaleY(scale);
|
||||
view.setAlpha(alpha);
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ package pub.doric.shader.slider;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
@ -35,6 +36,7 @@ import pub.doric.extension.bridge.DoricPlugin;
|
||||
import pub.doric.extension.bridge.DoricPromise;
|
||||
import pub.doric.shader.SuperNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.shader.slider
|
||||
@ -50,9 +52,10 @@ public class SliderNode extends SuperNode<RecyclerView> {
|
||||
private boolean loop = false;
|
||||
private String renderPageFuncId;
|
||||
private boolean scrollable = true;
|
||||
private String slideStyle = null;
|
||||
String slideStyle = null;
|
||||
private float minScale = 0.618f;
|
||||
private float maxScale = 1;
|
||||
private float galleryItemWidth = -1f;
|
||||
|
||||
private int slidePosition;
|
||||
private boolean needSlideToPosition;
|
||||
@ -64,10 +67,10 @@ public class SliderNode extends SuperNode<RecyclerView> {
|
||||
|
||||
@Override
|
||||
protected RecyclerView build() {
|
||||
RecyclerView recyclerView = new RecyclerView(getContext());
|
||||
final RecyclerView recyclerView = new RecyclerView(getContext());
|
||||
|
||||
|
||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()) {
|
||||
final SliderLayoutManager layoutManager = new SliderLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false) {
|
||||
@Override
|
||||
public boolean canScrollHorizontally() {
|
||||
if (!scrollable) {
|
||||
@ -88,10 +91,28 @@ public class SliderNode extends SuperNode<RecyclerView> {
|
||||
}
|
||||
};
|
||||
|
||||
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
final PagerSnapHelper snapHelper = new PagerSnapHelper();
|
||||
snapHelper.attachToRecyclerView(recyclerView);
|
||||
|
||||
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||
if (slideStyle.equals("gallery")) {
|
||||
int position = parent.getChildAdapterPosition(view);
|
||||
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
|
||||
assert layoutManager != null;
|
||||
int count = layoutManager.getItemCount();
|
||||
int interval = (recyclerView.getWidth() - DoricUtils.dp2px(SliderNode.this.galleryItemWidth)) / 2;
|
||||
if (position == 0) {
|
||||
outRect.left = interval;
|
||||
} else if (position == count - 1) {
|
||||
outRect.right = interval;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
recyclerView.setAdapter(this.slideAdapter);
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
@ -255,8 +276,24 @@ public class SliderNode extends SuperNode<RecyclerView> {
|
||||
this.slideStyle = prop.asString().value();
|
||||
} else if (prop.isObject()) {
|
||||
this.slideStyle = prop.asObject().getProperty("type").asString().value();
|
||||
this.maxScale = prop.asObject().getProperty("maxScale").asNumber().toFloat();
|
||||
this.minScale = prop.asObject().getProperty("minScale").asNumber().toFloat();
|
||||
if (this.slideStyle.equals("zoomOut")) {
|
||||
this.maxScale = prop.asObject().getProperty("maxScale").asNumber().toFloat();
|
||||
this.minScale = prop.asObject().getProperty("minScale").asNumber().toFloat();
|
||||
} else if (this.slideStyle.equals("gallery")) {
|
||||
float galleryMinScale = prop.asObject().getProperty("minScale").asNumber().toFloat();
|
||||
float galleryMinAlpha = prop.asObject().getProperty("minAlpha").asNumber().toFloat();
|
||||
this.galleryItemWidth = prop.asObject().getProperty("itemWidth").asNumber().toFloat();
|
||||
|
||||
SliderLayoutManager layoutManager = (SliderLayoutManager) mView.getLayoutManager();
|
||||
if (layoutManager != null) {
|
||||
layoutManager.setEnableGallery(true);
|
||||
layoutManager.setMinScale(galleryMinScale);
|
||||
layoutManager.setMinAlpha(galleryMinAlpha);
|
||||
layoutManager.setItemWidth(this.galleryItemWidth);
|
||||
this.slideAdapter.setItemWidth(this.galleryItemWidth);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "slidePosition":
|
||||
|
Reference in New Issue
Block a user