美文网首页
autojs模仿qq消息列表侧拉置顶删除菜单

autojs模仿qq消息列表侧拉置顶删除菜单

作者: 牙叔教程 | 来源:发表于2021-08-12 17:13 被阅读0次

    牙叔教程 简单易懂

    效果展示

    效果.gif

    思路

    使用安卓qq可知, 消息列表每次只能有一个侧拉菜单被打开


    思路.png

    autojs版本

    9.0.4

    你将学到以下知识点

    • RecyclerView的基本使用
    • 拦截rv的触摸事件
    • 禁止rv滚动
    • 设置rv的布局以及adapter
    • 为adapter添加更多的方法
    • 判断子控件菜单是否展开
    • 获取控件的rect
    • 获取控件在屏幕的绝对坐标
    • 判断触摸坐标是否在某个控件范围内
    • 设置rv的滚动监听事件
    • 判断rv滚动到顶部和底部
    • 获取rv第一个可见子view的position
    • HorizontalScrollView添加滚动监听
    • 图片转bitmap
    • 取消HorizontalScrollView底部的滑动条和滚动到底的阴影
    • HorizontalScrollView滚动到指定坐标
    • 通过子view获取rv的position
    • 置顶以及删除的rv更新操作
    • img设置bitmap
    • 获取屏幕内可见的rv子控件数量
    • 通过position获取屏幕内可见的子控件

    脚本概况

    • UI主要是一个RecyclerView, 子控件是HorizontalScrollView
    • HorizontalScrollView的左边是头像和聊天信息, 右边是侧拉菜单
    • 最多展开一个rv子控件菜单
    • 重点是在合适的时机拦截触摸事件, 思路看上面的流程图

    几个重要方法

    • hasExpandMenuView 判断有没有展开菜单的控件
    • isTouchCoordinateInViewRange 判断触摸坐标在不在指定view内部
    • onInterceptTouchEvent 拦截触摸事件
    • onTouchEvent 消费触摸事件
    • pointToPosition 通过触摸坐标获取rv子view的position

    难点

    • View.onInterceptTouchEvent 是用来决定是否拦截触摸事件,
      在MotionEvent.ACTION_DOWN事件return true, 就是拦截事件,
      return false就是不拦截事件
      确认拦截以后, 不再响应onInterceptTouchEvent, 而是完全交给onTouchEvent
    • View.onTouchEvent 是用来决定是否消费触摸事件,
      在MotionEvent.ACTION_DOWN事件return true, 就是消费事件,
      return false就是不消费事件

    代码讲解

    1. 导入类
    importClass(Packages.androidx.recyclerview.widget.LinearLayoutManager);
    importClass(Packages.androidx.recyclerview.widget.RecyclerView);
    importClass(android.content.pm.ActivityInfo);
    importClass(android.view.WindowManager);
    importClass(Packages.androidx.recyclerview.widget.DividerItemDecoration);
    importClass(android.graphics.BitmapFactory);
    importClass(android.graphics.Paint);
    importClass(android.graphics.Color);
    importClass(Packages.androidx.recyclerview.widget.GridLayoutManager);
    importClass(android.graphics.drawable.GradientDrawable);
    importClass(android.view.View);
    importClass(android.view.MotionEvent);
    importClass(android.widget.HorizontalScrollView);
    importClass(android.view.VelocityTracker);
    
    2. 导入子模块
    let dataList = require("./dataList");
    let setItemOnTouch = require("./setItemOnTouch");
    let onItemTouchListener = require("./onItemTouchListener");
    let onScrollListener = require("./onScrollListener");
    
    3. UI界面
    ui.layout(
      <vertical>
        <text text="牙叔教程 简单易懂" textSize="28sp" textColor="#fbfbfe" bg="#00afff" w="*" gravity="center"></text>
        <androidx.recyclerview.widget.RecyclerView id="recyclerView"></androidx.recyclerview.widget.RecyclerView>
      </vertical>
    );
    
    4. 设置recyclerView属性
    let layoutManager = new LinearLayoutManager(context);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(layoutManager);
    let recycleAdapter = createRecyclerViewAdapter(dataList);
    recyclerView.setAdapter(recycleAdapter);
    recycleAdapter.notifyDataSetChanged();
    recyclerView.addOnItemTouchListener(onItemTouchListener);
    recyclerView.addOnScrollListener(onScrollListener);
    
    5. 获取头像
    function getProfilePhoto() {
      let filePath = files.path("./牙叔正方形128.jpg");
      let img = images.read(filePath);
      let bitmap = img.getBitmap();
      events.on("exit", () => {
        bitmap.recycle();
        img.recycle();
      });
      return bitmap;
    }
    
    6. 创建rv的adapter
    function createRecyclerViewAdapter(dataList) {
      let boxXml = (
        <HorizontalScrollView h="100dp">
          <horizontal id="horizontalParent">
            {/* 消息 */}
            <horizontal>
                ...
            </horizontal>
            {/* 菜单 */}
            <horizontal id="menuParent" h="match_parent">
                ...
            </horizontal>
          </horizontal>
        </HorizontalScrollView>
      );
      return RecyclerView.Adapter({
        onCreateViewHolder: function (parent, viewType) {
          log("onCreateViewHolder");
          // 视图创建
          let view;
          let holder;
          view = ui.inflate(boxXml, parent, false);
          holder = JavaAdapter(RecyclerView.ViewHolder, {}, view);
            ...
          return holder;
        },
        onBindViewHolder: function (holder, position) {
          log("onBindViewHolder");
          // 数据绑定
            ...
        },
        getItemCount: function () {
          return dataList.length;
        },
        getItemViewType: function (position) {
          if ((position & 1) == 0) {
            return "EvenNumber";
          } else {
            return "OddNumber";
          }
        },
        getDataList: function () {
          return dataList;
        },
      });
    }
    
    7. isTouchCoordinateInViewRange
    function isTouchCoordinateInViewRange(view, x, y) {
      let LocationOnScreen = view.getLocationOnScreen();
      let frame = new Rect();
      view.getHitRect(frame);
      log("LocationOnScreen = ");
      log(LocationOnScreen);
      log("frame = " + frame);
      // 触摸点: x=511.5, y=180.5
      // Rect(0, 0 - 1470, 300)
      let left = LocationOnScreen[0];
      let top = LocationOnScreen[1];
      let width = frame.width();
      let height = frame.height();
      frame.left = left >= 0 ? left : 0;
      frame.top = top;
      frame.right = left + width;
      frame.bottom = top + height;
      log("子控件当前区域frame");
      log(frame);
      if (frame.contains(x, y)) {
        log("在控件内" + view);
        return true;
      } else {
        log("不在控件内" + view);
        log("触摸点: x=" + x + ", y=" + y);
        return false;
      }
    }
    

    名人名言

    思路是最重要的, 其他的百度, bing, stackoverflow, 安卓文档, autojs文档, 最后才是群里问问

    ----牙叔教程

    声明

    部分内容来自网络
    本教程仅用于学习, 禁止用于其他用途

    相关文章

      网友评论

          本文标题:autojs模仿qq消息列表侧拉置顶删除菜单

          本文链接:https://www.haomeiwen.com/subject/pjwlbltx.html