android 脚本swipe,Android自定义SwipeLayout仿QQ侧滑条目

本文介绍了一种自定义的Android SwipeLayout实现方法,通过该布局可以创建类似QQ消息列表的侧滑效果。布局支持左右两个方向的滑动操作,并且能够响应不同的滑动状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android自定义SwipeLayout仿QQ侧滑条目,供大家参考,具体内容如下

先看动图

a23903537b3fb1192675be44b5fb900b.gif

看布局文件

activity_main.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="www.weshared.qqcehua.MainActivity">

swipelayout.xml

android:id="@+id/swipelayout"

android:layout_width="match_parent"

android:layout_height="72dp">

android:id="@+id/back_left_tv_mark"

android:layout_width="84dp"

android:layout_height="match_parent"

android:background="@android:color/holo_blue_dark"

android:gravity="center"

android:text="Mark"

android:textColor="@android:color/white"

android:textSize="20sp" />

android:id="@+id/back_right_ll"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:layout_gravity="right"

android:orientation="horizontal">

android:id="@+id/back_right_tv_call"

android:layout_width="84dp"

android:layout_height="match_parent"

android:background="@android:color/holo_orange_dark"

android:gravity="center"

android:text="Call"

android:textColor="@android:color/white"

android:textSize="20sp" />

android:id="@+id/back_right_tv_delete"

android:layout_width="84dp"

android:layout_height="match_parent"

android:background="@android:color/holo_red_dark"

android:gravity="center"

android:text="Delete"

android:textColor="@android:color/white"

android:textSize="20sp" />

android:id="@+id/front_tv_content"

android:layout_width="match_parent"

android:layout_gravity="center"

android:gravity="center"

android:layout_height="match_parent"

android:background="#666666" />

在MainActivity中

public class MainActivity extends AppCompatActivity {

private SwipeLayout mSwipeLayout;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init();

}

private void init() {

mSwipeLayout = (SwipeLayout) findViewById(R.id.swipelayout);

mSwipeLayout.setOnClickListener(new SwipeLayout.OnClickListener() {

@Override

public void onClick(View view) {

switch (view.getId()) {

case R.id.back_left_tv_mark:

toast("mark");

break;

case R.id.front_tv_content:

toast("content");

break;

case R.id.back_right_tv_call:

toast("call");

break;

case R.id.back_right_tv_delete:

toast("delete");

break;

}

}

});

}

public void toast(String message) {

Toast toast = Toast.makeText(this, "", Toast.LENGTH_SHORT);

if (!TextUtils.isEmpty(message) && toast != null) {

toast.setText(message);

toast.show();

}

}

}

自定义SwipeLayout控件

public class SwipeLayout extends FrameLayout {

private View mBackLeftView;

private ViewGroup mBackRightView;

private View mFrontView;

private int mWidth;

private int mHeight;

private int mLeftRange;

private int mRightRange;

private int status;

public final int NORMAL = 0;//关闭状态

public final int LEFT_OPEN = 1;//左边打开状态

public final int RIGHT_OPEN = 2;//右边打开状态

public final int LEFT_OPENING = 3;//左边正打开状态

public final int LEFT_CLOSING = 4;//左边正关闭状态

public final int RIGHT_OPENING = 5;//右边正打开状态

public final int RIGHT_CLOSING = 6;//右边正关闭状态

private ViewDragHelper mViewDrawHelper;

private final int V = 300;//限制速度

private OnSwipeListener mOnSwipeListener;

private OnClickListener mOnClickListener;

private View mBackRightCall;

private View mBackRightDelete;

private int x;

private boolean isClick;

private final int DX = 10;

public interface OnSwipeListener {

void onLeftOpen(SwipeLayout swipeLayout);

void onLeftClose(SwipeLayout swipeLayout);

void onRightOpen(SwipeLayout swipeLayout);

void onRightClose(SwipeLayout swipeLayout);

}

public interface OnClickListener {

void onClick(View view);

}

public SwipeLayout(Context context) {

super(context);

init();

}

public SwipeLayout(Context context, AttributeSet attrs) {

super(context, attrs);

init();

}

public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init();

}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

init();

}

private void init() {

status = NORMAL;//默认是NORMAL

mViewDrawHelper = ViewDragHelper.create(this, callback);

}

public void setOnSwipeListener(OnSwipeListener mOnSwipeListener) {

this.mOnSwipeListener = mOnSwipeListener;

}

public void setOnClickListener(OnClickListener mOnClickListener) {

this.mOnClickListener = mOnClickListener;

}

private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {

/**是否试图拖拽子view*/

@Override

public boolean tryCaptureView(View child, int pointerId) {

if (child == mBackLeftView) {

return false;

}

return true;

}

/** 水平方向上的限制*/

@Override

public int clampViewPositionHorizontal(View child, int left, int dx) {

if (child == mFrontView) {

if (left < -mRightRange) {

left = -mRightRange;

} else if (left > mLeftRange) {

left = mLeftRange;

}

} else if (child == mBackRightView) {

if (left < mWidth - mRightRange) {

left = mWidth - mRightRange;

} else if (left > mWidth) {

left = mWidth;

}

}

return left;

}

/**这是系统定义的状态*/

@Override

public void onViewDragStateChanged(int state) {

super.onViewDragStateChanged(state);

if (state == ViewDragHelper.STATE_IDLE) {//ViewDrawHelper处于空闲状态

} else if (state == ViewDragHelper.STATE_DRAGGING) {//ViewDrawHelper处于正在拖拽状态

//拖拽状态,可设置滑动事件

} else if (state == ViewDragHelper.STATE_SETTLING) {//ViewDrawHelper处于飞翔状态

//飞翔状态设置,可设置滚动事件

}

}

@Override

public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {

super.onViewPositionChanged(changedView, left, top, dx, dy);

if (mFrontView == changedView) {

mBackRightView.offsetLeftAndRight(dx);

} else if (mBackRightView == changedView) {

mFrontView.offsetLeftAndRight(dx);

}

status = updateStatus();//更新控件的状态

invalidate();//重绘界面

}

@Override

public void onViewReleased(View releasedChild, float xvel, float yvel) {

super.onViewReleased(releasedChild, xvel, yvel);

int left = mFrontView.getLeft();

if (left < -mRightRange * 0.5f) {

if (xvel > V) {

normalClose();

} else {

rightOpen();

}

} else if (left >= -mRightRange * 0.5f && left <= 0) {

if (xvel < -V) {//向左滑动

rightOpen();//打开右边前布局

} else {

normalClose();

}

} else if (left > 0 && left <= mLeftRange * 0.5f) {

if (xvel > V) {

leftOpen();

} else {

normalClose();

}

} else if (left > mLeftRange * 0.5f && left <= mLeftRange) {

if (xvel < -V) {//向左滑动

normalClose();

} else {

leftOpen();

}

}

}

};

public void dispatchClickListener() {

//设置点击事件

if (status == LEFT_OPEN) {

//mark的点击事件和Content点击事件

if (mOnClickListener != null) {

if (x > 0 && x < mLeftRange) {

mOnClickListener.onClick(mBackLeftView);

}

}

} else if (status == RIGHT_OPEN) {

//call 和 Delete的点击事件 和Content点击事件

if (mOnClickListener != null) {

if (x > mWidth - mRightRange && x < mWidth - mRightRange * 0.5f) {

mOnClickListener.onClick(mBackRightCall);

} else if (x >= mWidth - mRightRange * 0.5f && x <= mWidth) {

mOnClickListener.onClick(mBackRightDelete);

}

}

} else if (status == NORMAL) {

//content的点击事件

if (mOnClickListener != null) {

mOnClickListener.onClick(mFrontView);

}

}

}

private int updateStatus() {

int left = mFrontView.getLeft();

if (left == -mRightRange) {

status = RIGHT_OPEN;

} else if (left == 0) {

status = NORMAL;

} else if (left == mLeftRange) {

status = LEFT_OPEN;

}

return status;

}

public void leftOpen() {

leftOpen(true);

}

public void leftOpen(boolean isSmooth) {

int finalLeft = mLeftRange;

int finalTop = 0;

if (isSmooth) {

if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) {

ViewCompat.postInvalidateOnAnimation(this);

}

} else {

layoutContent(LEFT_OPEN);

}

}

public void normalClose() {

normalClose(true);

}

public void normalClose(boolean isSmooth) {

int finalLeft = 0;

int finalTop = 0;

if (isSmooth) {

if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) {

ViewCompat.postInvalidateOnAnimation(this);

}

} else {

layoutContent(NORMAL);

}

}

public void rightOpen() {

rightOpen(true);

}

public void rightOpen(boolean isSmooth) {

int finalLeft = -mRightRange;

int finalTop = 0;

if (isSmooth) {

if (mViewDrawHelper.smoothSlideViewTo(mFrontView, finalLeft, finalTop)) {

ViewCompat.postInvalidateOnAnimation(this);

}

} else {

layoutContent(RIGHT_OPEN);

}

}

@Override

public void computeScroll() {

super.computeScroll();

if (mViewDrawHelper.continueSettling(true)) {

ViewCompat.postInvalidateOnAnimation(this);

}

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

return mViewDrawHelper.shouldInterceptTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

dispatchOnTouchEvent(event);//分发触摸的事件

try {

mViewDrawHelper.processTouchEvent(event);//将触摸事件传递给ViewDrawHelper

} catch (Exception e) {

}

return true;

}

public void dispatchOnTouchEvent(MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {

x = (int) event.getX();

isClick = true;

} else if (event.getAction() == MotionEvent.ACTION_MOVE) {

int movex = (int) event.getX();

if (Math.abs(movex - x) > DX) {//防止点击事件,会稍微手指抖动

isClick = false;

}

} else if (event.getAction() == MotionEvent.ACTION_UP) {

if (isClick) {

dispatchClickListener();

}

}

}

@Override

protected void onFinishInflate() {

super.onFinishInflate();

//获取控件中的子控件

mBackLeftView = getChildAt(0);

mBackRightView = (ViewGroup) getChildAt(1);

mFrontView = getChildAt(2);

mBackRightCall = mBackRightView.getChildAt(0);

mBackRightDelete = mBackRightView.getChildAt(1);

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

mWidth = getMeasuredWidth();

mHeight = getMeasuredHeight();

mLeftRange = mBackLeftView.getMeasuredWidth();

mRightRange = mBackRightView.getMeasuredWidth();

}

@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

super.onLayout(changed, left, top, right, bottom);

//摆放布局

layoutContent(NORMAL);

}

public void layoutContent(int status) {

Rect frontRect = computeFrontRect(status);//根据状态,摆放前布局

mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);

Rect rightBackRect = computeRightBackRect(frontRect);//根据前布局,摆放右边后布局

mBackRightView.layout(rightBackRect.left, rightBackRect.top, rightBackRect.right, rightBackRect.bottom);

}

public Rect computeFrontRect(int status) {

int left = 0;

int top = 0;

if (status == LEFT_OPEN) {

left = mLeftRange;

} else if (status == RIGHT_OPEN) {

left = -mRightRange;

}

return new Rect(left, top, left + mWidth, top + mHeight);

}

public Rect computeRightBackRect(Rect frontRect) {

int left = 0;

int top = 0;

if (frontRect != null) {

left = frontRect.right;

}

return new Rect(left, top, left + mRightRange, top + mHeight);

}

}

现在控件耦合程度太高,以后慢慢优化,写成一个库。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值