Android 简单的实现画廊效果
用一种较为简单的方式实现画廊效果(RecyclerView)
首先先上效果图:

思路:
对于这一个效果,主要要的部分和普通的RecyclerView没有太大的差别主要是获取当前需要放大的那一个Item。然后要对所有当前页面上可见的Item进行高度的改变(这里为了偷懒只改变了高度,如果要同时改变宽度的话其实方法不会差太多,就是在计算的缩放比例的时候改一改就好了)。
之前在做的时候一开始参考了 >>>这一篇博客<<< ,至于这一篇博客是怎么操作的我不多加说明了大家可以点链接过去看看。但是在使用的时候我这边不知道是由于说明原因通过 onScrolled(RecyclerView recyclerView, int dx, int dy) 获取到的横向的累计距离会在快速滑动的时候出错,所以就放弃了,但是中间我任然有一些借鉴,所以推荐大家也可以看一下。
具体步骤:
- 新建一个Card类继承RecyclerView
- 新建一个FinalValue类用来存一些已经确定的值(比如Item的pading,width)
- 新建一个r_Item视图作为Item的视图(这部分代码就不贴的)。
- 新建一个CardAdapt类继承RecyclerView.Adapter
- 新建一个ScaleHelper类用在滑动时对RecyclerView的各个Item的操作
首先是Card类(RecyclerView)
这一个类没有什么好多说的就是继承RecyclerView就好了。
接下来是CardAdapt
对于CardAdapt的话,我们需要添加一个方法 onCreateViewHolder 用于初始化卡片Item的宽度(高度)。
其中 FinalValue.LeftCard 是我们要显示的那个Item的两边的Item的显示出来的宽度(我这里没有设置边距所以不用管)。
public void onCreateViewHolder(ViewGroup parent, View itemView) {RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();lp.width = parent.getWidth() - Display.dip2px(itemView.getContext(), 2 * (FinalValue.LeftCard));itemView.setLayoutParams(lp);}
在这里用到了一个Display的类时用于不同单位之间的转换的类,下面给出代码。
private void onCreateViewHolder(ViewGroup parent, View itemView) {//设置宽度RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();lp.width = parent.getWidth() - DisplayUntil.dip2px(itemView.getContext(), 2 * (FinalValue.LeftCard));itemView.setLayoutParams(lp);}
2.为了可以使首尾两个Item也可以在屏幕中间显示
private void makecenter(View itemView, final int position, int itemCount) {//用于是首尾可以居中int padding = DisplayUntil.dip2px(itemView.getContext(), FinalValue.padding);itemView.setPadding(padding, 0, padding, 0);int leftMar = position == 0 ? padding + DisplayUntil.dip2px(itemView.getContext(), FinalValue.LeftCard) : 0;int rightMar = position == itemCount - 1 ? padding + DisplayUntil.dip2px(itemView.getContext(), FinalValue.LeftCard) : 0;setMargin(itemView, leftMar, 0, rightMar, 0);}private void setMargin(View view, int left, int top, int right, int bottom) {ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();if (lp.leftMargin != left || lp.topMargin != top || lp.rightMargin != right || lp.bottomMargin != bottom) {lp.setMargins(left, top, right, bottom);view.setLayoutParams(lp);}}
其余的代码就不多说了
private ArrayList mDatas = new ArrayList<>();public cardAdapt (ArrayList Data){mDatas = Data;}@NonNull@Overridepublic VH onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.r_item,viewGroup,false);onCreateViewHolder(viewGroup,view);return new VH(view);}@Overridepublic void onBindViewHolder(@NonNull VH vh, int i) {makecenter(vh.itemView,i,getItemCount());vh.mTextView.setText(mDatas.get(i));}@Overridepublic int getItemCount() {return mDatas.size();}class VH extends RecyclerView.ViewHolder{TextView mTextView;public VH(@NonNull View itemView) {super(itemView);mTextView = itemView.findViewById(R.id.ttv);}}
然后就是最重要的ScaleHelper类
首先是要用到的变量
if(now == -1 && mCurrentPos == 0)//当当前页面时首尾页面的时候,即便会出现当前页面可见但是now为-1的情况所以下面做特判{View view = mLayoutManager.findViewByPosition(mCurrentPos);if(view.getLeft() > 0){onScrolledChangedCallback();return ;}}if(now == -1 && mCurrentPos == mLayoutManager.getItemCount()-1){View view = mLayoutManager.findViewByPosition(mCurrentPos);if(view.getRight() > 0){onScrolledChangedCallback();return ;}}
2.真的只是没有页面完全可见,处理代码如下:
if(now!=-1)
{mCurrentPos = now;
}else if(last * dx <0)
{mCurrentPos += dx>0?1:-1;
}
last = dx;
然后在处理完之后调用对应的接下来会讲到的调整宽度的方法就可以了。
对于处理宽度的方法的话,其实就是根据获取到的当前的页面的position来获取主Item和两边的Item(如果有的话),再通过自己写的一个获取对应百分比的方法 getlper() (接下来会讲)来改变页面的高度,代码如下:
public void onScrolledChangedCallback() {View leftView = null;View currentView;View rightView = null;//页面赋值if (mCurrentPos > 0) {leftView = mCard.getLayoutManager().findViewByPosition(mCurrentPos - 1);}currentView = mCard.getLayoutManager().findViewByPosition(mCurrentPos);if (mCurrentPos < mCard.getAdapter().getItemCount() - 1) {rightView = mCard.getLayoutManager().findViewByPosition(mCurrentPos + 1);}//调整大小if (leftView != null) {int left = leftView.getLeft();float percent = getlper(left);leftView.setScaleY((float) (0.8 + 0.2 * percent));}if (currentView != null) {int left = currentView.getLeft();float percent = getlper(left);currentView.setScaleY((float) (0.8 + 0.2 * percent));}if (rightView != null) {int left = rightView.getLeft();float percent = getlper(left);rightView.setScaleY((float) (0.8 + 0.2 * percent));}}
接下来就是之前提到的获取当前页面应当显示的高度比例的方法,代码如下:
private float getlper(int left){if(left >= mAllWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard) || left <= -(mCardWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard))){return 0;}else if(left > mAllLeft ){left = mAllWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard) - left;return (float)(left * 1.0 / (mAllWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard) - mAllLeft));}else{left += (mCardWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard));return (float)(left * 1.0 / (mCardWidth - DisplayUntil.dip2px( mContext,FinalValue.LeftCard) + mAllLeft ));}}
还有不要忘记要添加一个方法,并调用:
private void initWidth() {mCard.post(new Runnable() {@Overridepublic void run() {Log.i("show", "run: ");mAllWidth = mLayoutManager.getWidth();mCardWidth = mAllWidth - DisplayUntil.dip2px(mContext, 2 * (FinalValue.LeftCard));mAllLeft = DisplayUntil.dip2px(mContext, (FinalValue.LeftCard));mCard.smoothScrollToPosition(mCurrentPos);//让RecycleView平滑滚动到指定位置(mCurrentItemPos) 同时要重写smoothScrollToPosition(RecyclerView, State, int)方法onScrolledChangedCallback();}});}
同时要实现一个方法用于关联对应的Card:
public void attachToRecyclerView(final cards mCard , LinearLayoutManager ml) {this.mCard = mCard;mContext = mCard.getContext();mLayoutManager = ml;addOnScrollListener();initWidth();mLinearSnapHelper.attachToRecyclerView(mCard);}
趁年轻,别给自己后悔的机会,错过了就什么都来不及了。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
