Android 如何在RecyclerView中放大整个内容?

Android 如何在RecyclerView中放大整个内容?,android,android-recyclerview,Android,Android Recyclerview,我需要在RecyclerView中放大/缩小整个内容。 事实上,我需要按宽度和每个项目内的文本调整所有子视图的大小 public class ViewHolder { Button btn; ... } 当用户进行放大时,按钮的文本应减少到8sp,如果用户继续放大,按钮的文本将消失 所以,现在我左右为难:我需要做什么?在适配器中调整项目大小,或在LayoutManager中调整项目大小,并更新整个适配器 这两种场景似乎都会影响视觉效果的表现,所以我需要帮助。也许你能给我一个

我需要在RecyclerView中放大/缩小整个内容。 事实上,我需要按宽度和每个项目内的文本调整所有子视图的大小

public class ViewHolder {

    Button btn;

    ...
}
当用户进行放大时,按钮的文本应减少到
8sp
,如果用户继续放大,按钮的文本将消失

所以,现在我左右为难:我需要做什么?在适配器中调整项目大小,或在LayoutManager中调整项目大小,并更新整个适配器

这两种场景似乎都会影响视觉效果的表现,所以我需要帮助。也许你能给我一个更好的解决办法


对于2016年11月21日的状态,我找不到任何适用于此情况的盒式解决方案。

所以我决定写我自己的视图,并在每次缩放比例因子改变时重新测量可见视图

您使用哪种适配器

我尝试了水平线性布局管理器,并调整了适配器内的项目大小:

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
           ...
           final ViewGroup.LayoutParams layoutParams = viewHolder.rootView.getLayoutParams();
           layoutParams.width = getItemWidth(position);   //width calculation using current zoom level
           layoutParams.height = mItemLayoutHeight;
           viewHolder.rootView.setLayoutParams(layoutParams);
           ...
活动/片段的setZoom(..)方法如下所示:

        public void setZoom(float newValue) {
           int dScroll = (int) ((ADAPTER_ZOOM - newValue) * getResources().getDisplayMetrics().widthPixels/2f);   //assume you Recycler view uses whole display 
           ADAPTER_ZOOM = newValue;
           resetBoundaries();
           //
           epgAdapter.notifyDataSetChanged();
           //
           epgRecyclerView.scrollBy(dScroll, 0);
        }

但是对于我的自定义LayoutManager,性能很差,似乎在LinearLayoutManager中有一个优化列表,用户可以使用此代码。它可以放大recyclerview的所有内容。

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;

/**
@author yogesh
* */
public class PinchRecyclerView extends RecyclerView {
    private static final int INVALID_POINTER_ID = -1;
    private int mActivePointerId = INVALID_POINTER_ID;
    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;
    private float maxWidth = 0.0f;
    private float maxHeight = 0.0f;
    private float mLastTouchX;
    private float mLastTouchY;
    private float mPosX;
    private float mPosY;
    private float width;
    private float height;


    public PinchRecyclerView(Context context) {
        super(context);
        if (!isInEditMode())
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
    }

    public PinchRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        if (!isInEditMode())
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
    }

    public PinchRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (!isInEditMode())
            mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return super.onInterceptTouchEvent(ev);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent ev) {
        super.onTouchEvent(ev);
        final int action = ev.getAction();
        mScaleDetector.onTouchEvent(ev);
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();
                mLastTouchX = x;
                mLastTouchY = y;
                mActivePointerId = ev.getPointerId(0);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                /* this line is replaced because here came below isssue
                java.lang.IllegalArgumentException: pointerIndex out of range
                 ref http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch
                */
                //final int pointerIndex = ev.findPointerIndex(mActivePointerId);

                final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);
                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;

                mPosX += dx;
                mPosY += dy;

                if (mPosX > 0.0f)
                    mPosX = 0.0f;
                else if (mPosX < maxWidth)
                    mPosX = maxWidth;

                if (mPosY > 0.0f)
                    mPosY = 0.0f;
                else if (mPosY < maxHeight)
                    mPosY = maxHeight;

                mLastTouchX = x;
                mLastTouchY = y;

                invalidate();
                break;
            }

            case MotionEvent.ACTION_UP: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_CANCEL: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_POINTER_UP: {
                final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = ev.getX(newPointerIndex);
                    mLastTouchY = ev.getY(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;
            }
        }

        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.translate(mPosX, mPosY);
        canvas.scale(mScaleFactor, mScaleFactor);
        canvas.restore();
    }

    @Override
    protected void dispatchDraw(@NonNull Canvas canvas) {
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        if (mScaleFactor == 1.0f) {
            mPosX = 0.0f;
            mPosY = 0.0f;
        }
        canvas.translate(mPosX, mPosY);
        canvas.scale(mScaleFactor, mScaleFactor);
        super.dispatchDraw(canvas);
        canvas.restore();
        invalidate();
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();
            mScaleFactor = Math.max(1.0f, Math.min(mScaleFactor, 3.0f));
            maxWidth = width - (width * mScaleFactor);
            maxHeight = height - (height * mScaleFactor);
            invalidate();
            return true;
        }
    }
}
导入android.content.Context;
导入android.graphics.Canvas;
导入android.support.annotation.NonNull;
导入android.support.v7.widget.RecyclerView;
导入android.util.AttributeSet;
导入android.view.MotionEvent;
导入android.view.scalegestruedetector;
/**
@作者约格什
* */
公共类PinchRecycleView扩展了RecycleView{
私有静态final int无效\u指针\u ID=-1;
private int mActivePointerId=无效的\u指针\u ID;
专用scalegestruedetector mScaleDetector;
私人浮动mScaleFactor=1.f;
专用浮点最大宽度=0.0f;
专用浮动最大高度=0.0f;
私有浮动mLastTouchX;
私密的浮躁和敏感;
私人浮动mPosX;
私家车;
私有浮动宽度;
私人浮动高度;
公共PinchRecycleView(上下文){
超级(上下文);
如果(!isInEditMode())
mScaleDetector=新的ScaleGetDetector(getContext(),new ScaleListener());
}
公共PinchRecycleView(上下文、属性集属性){
超级(上下文,attrs);
如果(!isInEditMode())
mScaleDetector=新的ScaleGetDetector(getContext(),new ScaleListener());
}
公共PinchRecycleView(上下文上下文、属性集属性、int defStyleAttr){
super(上下文、attrs、defStyleAttr);
如果(!isInEditMode())
mScaleDetector=新的ScaleGetDetector(getContext(),new ScaleListener());
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
宽度=MeasureSpec.getSize(widthMeasureSpec);
高度=测量等级getSize(高度测量等级);
超级测量(宽度测量、高度测量);
}
@凌驾
公共布尔值onInterceptTouchEvent(MotionEvent ev){
试一试{
返回超级onInterceptTouchEvent(ev);
}捕获(IllegalArgumentException ex){
例如printStackTrace();
}
返回false;
}
@凌驾
公共布尔onTouchEvent(@NonNull MotionEvent ev){
超级火山口(ev);
final int action=ev.getAction();
mScaleDetector.onTouchEvent(ev);
开关(动作和动作事件.动作屏蔽){
case MotionEvent.ACTION\u DOWN:{
最终浮点数x=ev.getX();
最终浮动y=ev.getY();
mLastTouchX=x;
mLastTouchY=y;
MacTivePointId=ev.getPointerId(0);
打破
}
case MotionEvent.ACTION\u移动:{
/*这一行被替换,因为下面是ISSUE
java.lang.IllegalArgumentException:指针索引超出范围
裁判http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch
*/
//final int pointerIndex=ev.findPointerIndex(mactivePointId);
final int pointerIndex=(action&MotionEvent.action\u POINTER\u INDEX\u MASK)
>>MotionEvent.ACTION\u指针\u索引\u移位;
最终浮动x=ev.getX(指针索引);
最终浮动y=ev.getY(指针索引);
最终浮点数dx=x-mLastTouchX;
最终浮子dy=y—最大浮子厚度;
mPosX+=dx;
mPosY+=dy;
如果(mPosX>0.0f)
mPosX=0.0f;
否则如果(mPosX0.0f)
mPosY=0.0f;
否则如果(mPosY<最大高度)
mPosY=最大高度;
mLastTouchX=x;
mLastTouchY=y;
使无效();
打破
}
case MotionEvent.ACTION\u UP:{
MacTivePointId=无效的\u指针\u ID;
打破
}
case MotionEvent.ACTION\u取消:{
MacTivePointId=无效的\u指针\u ID;
打破
}
case MotionEvent.ACTION\u指针\u向上:{
final int pointerIndex=(action&MotionEvent.action\u POINTER\u INDEX\u MASK)>>MotionEvent.action\u POINTER\u INDEX\u SHIFT;
final int pointerId=ev.getPointerId(pointerIndex);
if(pointerId==MacTivePointId){
final int newPointerIndex=pointerIndex==0?1:0;
mLastTouchX=ev.getX(newPointerIndex);
mLastTouchY=ev.getY(新指针索引);
MacTivePointId=ev.getPointerId(newPointerIndex);
}
打破
}
}
返回true;
}
@凌驾
公共空白onDraw(画布){
super.onDraw(帆布);
canvas.sav