侧滑菜单是一种很有意思的布局方式,视觉上看起来很灵活,个人非常喜欢。
其实侧滑菜单实现起来并不难,实现的方式很多,我是在item view上做的文章,优点就是可移植,可适用于RecyclerView、ListView等。
item view的最外层使用SideslipView,SideslipView就是我们今天的主角,其实SideslipView是继承了HorizontalScrollView,说到这里是不是就已经很清楚了,HorizontalScrollView本身就是一种可滑动的布局,我们只需在onTouchEvent中做一些控制,让效果看起来灵动一些。
ok,奉上SideslipView代码
public class SideslipView extends HorizontalScrollView {
private Coordinate startCoordinate;
public SideslipView(Context context) {
super(context);
init();
}
public SideslipView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SideslipView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
startCoordinate = new Coordinate();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (!startCoordinate.isTag()){
startCoordinate.setX(ev.getX());
startCoordinate.setY(ev.getY());
startCoordinate.setTag(true);
}
break;
case MotionEvent.ACTION_UP:
handlerEvent(ev);
case MotionEvent.ACTION_CANCEL:
return true;
default:
break;
}
return super.onTouchEvent(ev);
}
private void handlerEvent(MotionEvent event) {
float poorX = startCoordinate.getX() - event.getX();
float childWidth = 0f;
//遍历子View得到HorizontalScrollView总宽度
for (int i =0;i<getChildCount();i++){
View view = getChildAt(i);
childWidth += view.getWidth();
}
childWidth = (childWidth - getScreenWidth(getContext())) / 2;
if (poorX < -childWidth || (poorX <= childWidth && poorX >= 0)){
this.smoothScrollTo(0, 0);
startCoordinate.setTag(false);
}
if (poorX > childWidth || (poorX >= -childWidth && poorX <= 0)){
this.smoothScrollTo(this.getMeasuredWidth(), 0);
startCoordinate.setTag(false);
}
}
//坐标类
class Coordinate{
boolean tag = false;
public boolean isTag() {
return tag;
}
public void setTag(boolean tag) {
this.tag = tag;
}
float x;
float y;
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
}
//获得屏幕尺寸, 建议使用时把这个方法重构到工具类中
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE );
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels ;
}
}
使用时需要注意,最初状态下展示的View,一定要设置以下代码,否则视图无法充满。
//kotlin实现
var layout = imageView.layoutParams
val wm = context
.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val outMetrics = DisplayMetrics()
wm.defaultDisplay.getMetrics(outMetrics)
layout.width = outMetrics.widthPixels
imageView.requestLayout()
最后附上效果图:

笔者能力有限,不足之处欢迎指出!
网友评论