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