英文:
CenterCrop image with slow zoom out
问题
public class HorizontalGalleryRecyclerViewAdapter extends RecyclerView.Adapter<HorizontalGalleryRecyclerViewAdapter.MyViewHolder> {
private Context mContext;
private ArrayList<ImageItems> arrayList;
public long Last_position;
private HorizontalGalleryRecyclerViewAdapter.onItemCLickListener mListener;
public interface onItemCLickListener {
void onItemClick(int mPosition);
}
public void setOnItemClickListener(HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
mListener = listener;
}
public HorizontalGalleryRecyclerViewAdapter(Context context, ArrayList<ImageItems> arrayList) {
this.mContext = context;
this.arrayList = arrayList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MyViewHolder((LayoutInflater.from(mContext).inflate(R.layout.horizontal_gallery_recycleriew_item, parent, false)), mListener);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Glide.with(mContext)
.load(arrayList.get(position).ImagePath)
.placeholder(R.drawable.background_gallery_placeholder)
.error(R.drawable.background_gallery_placeholder)
.thumbnail(0.5f).into(holder.img);
Last_position = position;
}
@Override
public int getItemCount() {
return arrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public RoundedImageView img;
public MyViewHolder(View view, final HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
super(view);
img = view.findViewById(R.id.horizontal_img);
img.setScaleX(1.1f);
img.setScaleY(1.1f);
img.animate().setDuration(3000).setStartDelay(1000)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(getAdapterPosition());
}
}
}
});
}
}
}
英文:
I have created a horizontal recyclerview
that shows images taken by a user. These images are center cropped and are displayed using Glide. How can I achieve a slow zoom out while the user is viewing the displayed image.
Please refer to this as an example:
https://dribbble.com/shots/8582397-Nomad-iOS-UI-Kit-Favorite-Places
UPDATE:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
public class HorizontalGalleryRecyclerViewAdapter extends RecyclerView.Adapter < HorizontalGalleryRecyclerViewAdapter.MyViewHolder > {
private Context mContext;
private ArrayList < ImageItems > arrayList;
public long Last_position;
private HorizontalGalleryRecyclerViewAdapter.onItemCLickListener mListener;
public interface onItemCLickListener {
void onItemClick(int mPosition);
}
public void setOnItemClickListener(HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
mListener = listener;
}
public HorizontalGalleryRecyclerViewAdapter(Context context, ArrayList < ImageItems > arrayList) {
this.mContext = context;
this.arrayList = arrayList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MyViewHolder((LayoutInflater.from(mContext).inflate(R.layout.horizontal_gallery_recycleriew_item, parent, false)), mListener);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
Glide.with(mContext)
.load(arrayList.get(position).ImagePath)
.placeholder(R.drawable.background_gallery_placeholder)
.error(R.drawable.background_gallery_placeholder)
.thumbnail(0.5 f).into(holder.img);
Last_position = position;
}
@Override
public int getItemCount() {
return arrayList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public RoundedImageView img;
public MyViewHolder(View view, final HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
super(view);
img = view.findViewById(R.id.horizontal_img);
img.setScaleX(1.1 f);
img.setScaleY(1.1 f);
img.animate().setDuration(3 _000).setStartDelay(1 _000)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(getAdapterPosition());
}
}
}
});
}
}
}
<!-- end snippet -->
答案1
得分: 1
这个效果可以通过缩小图像来实现。我创建了一个小的演示,没有使用RecyclerView
,只是作为一个展示,所以当一个视图被回收时,不要忘记调用view.animate().cancel()
。
为了能够缩小图像,我首先将其放大,然后进行缩小动画。
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View view = findViewById(R.id.image);
view.setScaleX(1.1f);
view.setScaleY(1.1f);
view.animate().setDuration(3_000).setStartDelay(1_000)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
}
}
在这个示例中,我选择了android:scaleType="centerCrop"
,但是当你使用Glide
进行操作时,你应该能够达到相同的效果。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/image" />
</FrameLayout>
为了在你的实现中实现缩放效果,你应该在每次绑定时设置初始缩放。
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.img.setScaleX(1.1f);
holder.img.setScaleY(1.1f);
Glide.with(mContext)
.load(arrayList.get(position).ImagePath)
.placeholder(R.drawable.background_gallery_placeholder)
.error(R.drawable.background_gallery_placeholder)
.thumbnail(0.5f).into(holder.img);
}
ViewHolder
本身只应该包含查找视图的逻辑。
public static class MyViewHolder extends RecyclerView.ViewHolder {
public RoundedImageView img;
public MyViewHolder(View view, final HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
super(view);
img = view.findViewById(R.id.horizontal_img);
view.setOnClickListener(...);
}
}
棘手的部分是实际启动动画,因为当前的查看状态不是适配器的一部分。你需要从外部提供它。然后,你可以通过 notifyItemChanged(int,Object)
的负载来提供信息,并在 onBindViewHolder(VH,int,List)
中处理它。但是最终,对于你的用例,onViewAttachedToWindow(VH)
可能已经足够了。
private void startAnimation(VH viewHolder, long duration, long delay) {
viewHolder.img.animate()
.setDuration(duration).setStartDelay(delay)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
}
英文:
This effect could be achieved by scaling down the image. I created a small demo without a RecyclerView
as a showcase, so don't forget to call view.animate().cancel()
when a view gets recycled.
To be able to scale down the image, I scaled it up first. Then I animated the downscale.
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View view = findViewById(R.id.image);
view.setScaleX(1.1f);
view.setScaleY(1.1f);
view.animate().setDuration(3_000).setStartDelay(1_000)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
}
}
I chose android:scaleType="centerCrop"
in this example, but you should be able to achieve the same when you do the operation with Glide
.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/image" />
</FrameLayout>
To achieve the scaling with your implementation, you should set the initial scale with every binding.
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
holder.img.setScaleX(1.1 f);
holder.img.setScaleY(1.1 f);
Glide.with(mContext)
.load(arrayList.get(position).ImagePath)
.placeholder(R.drawable.background_gallery_placeholder)
.error(R.drawable.background_gallery_placeholder)
.thumbnail(0.5 f).into(holder.img);
}
The ViewHolder
itself should only contain the logic for finding the view.
public static class MyViewHolder extends RecyclerView.ViewHolder {
public RoundedImageView img;
public MyViewHolder(View view, final HorizontalGalleryRecyclerViewAdapter.onItemCLickListener listener) {
super(view);
img = view.findViewById(R.id.horizontal_img);
view.setOnClickListener(...);
}
}
The tricky part is to actually start the animation, since the current viewing state is not part of the adapter. You'd have to provide it from outside. You could then provide the information with the payload of notifyItemChanged(int,Object)
and handle it in onBindViewHolder(VH,int,List)
instead. But eventually onViewAttachedToWindow(VH)
could be sufficient for your usecase.
private void startAnimation(VH viewHolder, long duration, long delay) {
viewHolder.img.animate()
.setDuration(duration).setStartDelay(delay)
.setInterpolator(new AccelerateDecelerateInterpolator())
.scaleX(1).scaleY(1).start();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论