效果图:
布局中去指定自定义 FrameLayout:
- <!-- 自定义仿 QQ 列表 Item 滑动 -->
- <view.custom.shangguigucustomview.MyCustomFrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="80dp"
- android:orientation="vertical"
- tools:context=".ShangGuiguTestActivity"
- android:background="@android:color/darker_gray">
- <TextView
- android:id="@+id/tv_content"
- android:layout_width="match_parent"
- android:layout_height="80dp"
- android:background="@android:color/white"
- android:textColor="@android:color/black"
- android:textSize="20dp"
- android:text="你有一条消息未读"
- android:gravity="center"
- android:drawableLeft="@mipmap/ic_launcher_round"
- android:paddingRight="40dp"
- />
- <TextView
- android:id="@+id/tv_menu"
- android:layout_width="wrap_content"
- android:layout_height="80dp"
- android:background="@android:color/holo_orange_dark"
- android:textColor="#f00000"
- android:textSize="20dp"
- android:text="删除"
- android:gravity="center"
- android:paddingLeft="30dp"
- android:paddingRight="30dp"
- />
- </view.custom.shangguigucustomview.MyCustomFrameLayout>
自定义 FrameLayout:
- public class MyCustomFrameLayout extends FrameLayout { // 继承于 FrameLayout 属于继承 ViewGroup, 因为它包含了孩子
- private static final String TAG = MyCustomFrameLayout.class.getSimpleName();
- /**
- * 拿到两个控件的宽和三个的高
- * @param context
- * @param attrs
- */
- private int myHeigth; // 统一的高度
- private int myContentWidth; // 中间内容 TextView 的宽度
- private int myMenuWidth; // 菜单的宽度
- private Scroller scroller;
- public MyCustomFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
- super(context, attrs);
- scroller = new Scroller(context);
- }
- private View tvContent;
- private View tvMenu;
- /**
- * 当布局加载完成? 后就会回调此方法
- */
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- tvContent = getChildAt(0); // 拿到第一个孩子
- tvMenu = getChildAt(1); // 得到第二个孩子
- }
- /**
- * 测量两个孩子的高宽
- * @param widthMeasureSpec
- * @param heightMeasureSpec
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- myContentWidth = tvContent.getMeasuredWidth(); // 等价于 getMeasuredWidth(); 因为这个是后去父控件的宽度, 父控件和这个孩子控件宽度是一样的
- myHeigth = getMeasuredHeight();
- myMenuWidth = tvMenu.getMeasuredWidth();
- }
- /**
- * 为何不让实现者强制重写, 应该在 FrameLayout 中已经重写过了
- * @param changed
- * @param left
- * @param top
- * @param right
- * @param bottom
- */
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- // 指定位置
- tvContent.layout(0, 0, myContentWidth, myHeigth);
- tvMenu.layout(myContentWidth, 0 , myContentWidth + myMenuWidth, myHeigth);
- }
- private float startX;
- private int x;
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()){
- case MotionEvent.ACTION_DOWN:
- startX = event.getX();
- break;
- case MotionEvent.ACTION_UP:
- float upEnd = event.getX();
- float thisUp = upEnd;
- // float myx = getScrollX() - thisUp;
- if (getScrollX()> myMenuWidth / 2) {
- // x = myMenuWidth;
- openM();
- } else {
- // x = 0;
- closeM();
- }
- /*invalidate();
- scroller.startScroll(getScrollX(), getScrollY(), x, Math.abs(1000));*/
- // scrollTo(x, getScrollY());
- break;
- case MotionEvent.ACTION_MOVE:
- int endX = (int) event.getX();
- int thisX = (int) (endX - startX);
- int scrollX = getScrollX();
- Log.i(TAG, ">>>>> scrollX" + scrollX);
- x = scrollX - thisX;
- // 非法值的屏蔽
- if (x <0) {
- x = 0;
- } else if (x> myMenuWidth) {
- x = myMenuWidth;
- }
- scrollTo(x, getScrollY());
- startX = event.getX();
- break;
- default:
- break;
- }
- return true;
- }
- private void openM() {
- invalidate();
- int dx = myMenuWidth - getScrollX();
- scroller.startScroll(getScrollX(), getScrollY(), dx, Math.abs(1000));
- }
- private void closeM() {
- invalidate();
- int dx = 0 - getScrollX();
- scroller.startScroll(getScrollX(), getScrollY(), dx, Math.abs(1000));
- }
- @Override
- public void computeScroll() {
- super.computeScroll();
- if (scroller.computeScrollOffset()) {
- int currX = scroller.getCurrX();
- scrollTo(currX, 0);
- invalidate();
- }
- }
- }
来源: http://www.bubuko.com/infodetail-2770948.html