Android 带recycleview的左滑动布局
我正试图使这个布局,正确的部分(黄色)必须始终是可访问的。我尝试使用抽屉布局,但没有找到移除scim的方法。scim块位于右侧部分 我本来打算使用de-SlidingPanelLayout,但它已被弃用。所以我创建了自己的布局Android 带recycleview的左滑动布局,android,android-recyclerview,Android,Android Recyclerview,我正试图使这个布局,正确的部分(黄色)必须始终是可访问的。我尝试使用抽屉布局,但没有找到移除scim的方法。scim块位于右侧部分 我本来打算使用de-SlidingPanelLayout,但它已被弃用。所以我创建了自己的布局 public class LeftSlidingLayout extends FrameLayout { private static final int LEFT = 0; private static final int RIGHT = 1;
public class LeftSlidingLayout extends FrameLayout
{
private static final int LEFT = 0;
private static final int RIGHT = 1;
private static final int DEFAULT_ALWAYS_SWIPEABLE_WIDTH = 35;
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
private static final int MAX_ANIMATION_DURATION = 500;
public static final int EXCLUSION_ZONE_HEIGHT = 100;
private int _alwaysSwipeableWidth;
private int _xDelta;
private int _xDown;
private Rect _bottomExlusionSwipeableZone;
public LeftSlidingLayout(final Context context)
{
this(context, null);
}
public LeftSlidingLayout(final Context context, final AttributeSet attrs)
{
this(context, attrs, 0);
}
public LeftSlidingLayout(final Context context, final AttributeSet attrs, final int defStyleAttr)
{
this(context, attrs, defStyleAttr, 0);
}
public LeftSlidingLayout(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.LeftSlidingLayout);
setAlwaysSwipeableWidth(attributes.getDimensionPixelOffset(R.styleable.LeftSlidingLayout_always_swipeable_width, DEFAULT_ALWAYS_SWIPEABLE_WIDTH));
attributes.recycle();
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)
{
final int adjustedWidth = widthMeasureSpec + getAlwaysSwipeableWidth();
super.onMeasure(adjustedWidth, heightMeasureSpec);
}
private Rect getBottomExlusionSwipeableZone()
{
return new Rect(getWidth() - getAlwaysSwipeableWidth(),
getHeight() - EXCLUSION_ZONE_HEIGHT,
getWidth(),
getHeight());
}
public void setAlwaysSwipeableWidth(final int alwaysSwipeableWidth)
{
_alwaysSwipeableWidth = alwaysSwipeableWidth;
setPadding(getPaddingLeft(),
getPaddingTop(),
getPaddingRight() + _alwaysSwipeableWidth,
getPaddingBottom());
}
public int getAlwaysSwipeableWidth()
{
return _alwaysSwipeableWidth;
}
@Override
public boolean onTouchEvent(final MotionEvent event)
{
if(isNotSwipeable(event))
return false;
final int X = (int) event.getRawX();
final long duration = event.getEventTime() - event.getDownTime();
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
final ViewGroup.MarginLayoutParams lParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
_xDelta = X - lParams.leftMargin;
_xDown = X;
break;
case MotionEvent.ACTION_UP:
animateAdjustment(_xDown - X, duration);
break;
case MotionEvent.ACTION_MOVE:
slideLeft(formatWithingBound(X - _xDelta, -getWidth() + getAlwaysSwipeableWidth(), 0));
break;
default:
//Do nothing
}
((View) getParent()).invalidate();
return true;
}
private boolean isNotSwipeable(final MotionEvent event)
{
return !isOpen() && getBottomExlusionSwipeableZone().contains((int) event.getX(), (int) event.getY());
}
private void animateAdjustment(final int swipedPixelDistance, final float durationInMs)
{
final float velocityInMsX = swipedPixelDistance / durationInMs;
if(velocityInMsX == 0 || swipedPixelDistance == 0)
return;
final int direction;
if(Math.abs(swipedPixelDistance) > SWIPE_THRESHOLD && Math.abs(velocityInMsX) > SWIPE_VELOCITY_THRESHOLD)
{
direction = swipedPixelDistance < 0 ? LEFT : RIGHT;
}
else
{
direction = swipedPixelDistance < 0 ? RIGHT : LEFT;
}
animateCurrentView(direction == LEFT ? -getWidth() + getAlwaysSwipeableWidth() : 0, velocityInMsX);
}
private void animateCurrentView(final int endMargin, final float speed)
{
final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
final int startMargin = layoutParams.leftMargin;
final Animation animation = new Animation()
{
@Override
protected void applyTransformation(final float interpolatedTime, final Transformation transformation)
{
slideLeft(startMargin + (int) ((endMargin - startMargin) * interpolatedTime));
}
};
final long duration = calculateDuration(startMargin, endMargin, speed);
animation.setDuration(Math.min(duration, MAX_ANIMATION_DURATION));
startAnimation(animation);
}
private void slideLeft(final int leftMargin)
{
final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
layoutParams.leftMargin = leftMargin;
setLayoutParams(layoutParams);
}
private long calculateDuration(final int startMargin, final int endMargin, final float speed)
{
return Math.abs((long) ((endMargin - startMargin) / speed));
}
private int formatWithingBound(final int valueToFormat, final int minBound, final int maxBound)
{
return Math.max(Math.min(valueToFormat, maxBound), minBound);
}
public void open()
{
animateCurrentView(0, 1);
}
public void closes()
{
animateCurrentView(-getWidth() + getAlwaysSwipeableWidth(), 1);
}
public boolean isOpen()
{
final ViewGroup.MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
return layoutParams.leftMargin == 0;
}
public interface SlidingListener
{
void onLeftMarginChanged(final int leftMargin);
}
}
公共类LeftSlidingLayout扩展了FrameLayout
{
私有静态final int LEFT=0;
私有静态final int RIGHT=1;
私有静态最终整数默认值总是可开关宽度=35;
专用静态最终整数滑动\u阈值=100;
专用静态最终整数滑动速度阈值=100;
私有静态最终int MAX_ANIMATION_DURATION=500;
公共静态最终内部隔离区高度=100;
私有int_始终可擦除宽度;
私人国际电信公司;
私人内部网络;
私有矩形底部ExlusionsWipeTableZone;
公共左滑块布局(最终上下文)
{
这个(上下文,空);
}
公共LeftSlidingLayout(最终上下文,最终属性集属性)
{
这(上下文,属性,0);
}
公共LeftSlidingLayout(最终上下文上下文、最终属性集属性、最终int defStyleAttr)
{
这(context,attrs,defStyleAttr,0);
}
公共LeftSlidingLayout(最终上下文上下文、最终属性集属性、最终整型defStyleAttr、最终整型defStyleRes)
{
super(context、attrs、defStyleAttr、defStyleRes);
最终类型Darray attributes=context.actainStyledAttributes(attrs,R.styleable.LeftSlidingLayout);
setAlwaysSwipeableWidth(attributes.getDimensionPixelOffset(R.styleable.LeftSlidingLayout_always_swipeable_width,默认值_always_swipeable_width));
attributes.recycle();
}
@凌驾
测量时的保护空隙(最终内部宽度测量等级、最终内部高度测量等级)
{
最终整数调整宽度=宽度测量等级+getAlwaysSwipeableWidth();
超级测量(调整宽度、高度测量值);
}
private Rect GetBottomExlusionsWipeTableZone()的
{
返回新的Rect(getWidth()-getAlwaysSwipeableWidth(),
getHeight()-排除区高度,
getWidth(),
getHeight());
}
公共无效设置alwaysSwipeableWidth(最终整数alwaysSwipeableWidth)
{
_alwaysSwipeableWidth=alwaysSwipeableWidth;
setPadding(getPaddingLeft(),
getPaddingTop(),
getPaddingRight(),
getPaddingBottom());
}
public int getAlwaysSwipeableWidth()
{
返回_alwaysSwipeableWidth;
}
@凌驾
公共布尔onTouchEvent(最终运动事件)
{
如果(不可切换(事件))
返回false;
final int X=(int)event.getRawX();
最终长持续时间=event.getEventTime()-event.getDownTime();
开关(event.getAction()&MotionEvent.ACTION\u掩码)
{
case MotionEvent.ACTION\u DOWN:
final ViewGroup.MarginLayoutParams lParams=(ViewGroup.MarginLayoutParams)getLayoutParams();
_xDelta=X-lParams.leftMargin;
_xDown=X;
打破
case MotionEvent.ACTION\u UP:
动画调整(xDown-X,持续时间);
打破
case MotionEvent.ACTION\u移动:
slideLeft(formatWithingBound(X-xDelta,-getWidth()+getAlwaysSwipeableWidth(),0));
打破
违约:
//无所事事
}
((视图)getParent()).invalidate();
返回true;
}
私有布尔值不可切换(最终MotionEvent事件)
{
return!isOpen()和&getbottomexlusionswipablezone()。包含((int)event.getX(),(int)event.getY());
}
私有void动画调整(最终整数旋转像素距离、最终浮点持续时间)
{
最终浮点速度InMsx=swipedPixelDistance/durationInMs;
if(VelocityInIMSx==0 | | swipedPixelDistance==0)
返回;
最终整数方向;
if(Math.abs(swipedPixelDistance)>滑动阈值和&Math.abs(velocityInMsX)>滑动速度阈值)
{
方向=旋转像素距离<0?左:右;
}
其他的
{
方向=旋转像素距离<0?右:左;
}
animateCurrentView(方向==左?-getWidth()+GetAlwaysWipeableWidth():0,速度inMsx);
}
私有void animateCurrentView(最终的int-endMargin,最终的浮点速度)
{
final ViewGroup.MarginLayoutParams layoutParams=(ViewGroup.MarginLayoutParams)getLayoutParams();
final int startMargin=布局参数leftMargin;
最终动画=新动画()
{
@凌驾
受保护的无效应用转换(最终浮点插值时间,最终转换)
{
slidelft(startMargin+(int)((endMargin-startMargin)*插值时间);
}
};
最终长持续时间=计算(起始边缘、结束边缘、速度);
setDuration(Math.min(duration,MAX_animation_duration));
startAnimation(动画);
}
私有void slideLeft(最终整型左边距)
{
final ViewGroup.MarginLayoutParams layoutParams=(ViewGroup.MarginLayoutParams)getLayoutParams();
layoutParams.leftMargin=leftMargin;
setLayoutParams(layoutParams);
}
专用长计算(最终整数起始边距、最终整数结束边距、最终浮点速度)
{
返回数学值abs((长)((endMargin-startMargin)/速度);
}
私有int-formatWithingBound(最终int-valueToFormat、最终int-minBound、最终int-maxBound)
{
返回Math.max(Math.min(valueToFormat,maxBound),minBound);
}
公开作废
{
动画片
@Override
public void computeScroll()
{
super.computeScroll();
if(!_hasScrim)
{
try
{
overrideScrimOpacity();
}
catch(final ReflectionException ignore)
{}
}
}
protected void overrideScrimOpacity() throws ReflectionException
{
try
{
FieldUtils.writeField(this, "mScrimOpacity", 0, true);
}
catch(final IllegalAccessException | IllegalArgumentException e)
{
throw new ReflectionException();
}
}