autojs模仿qq消息列表側拉置頂刪除菜單

牙叔教程 簡單易懂javascript

效果展現

效果.gif

思路

使用安卓qq可知, 消息列表每次只能有一個側拉菜單被打開 思路.pngjava

autojs版本

9.0.4android

你將學到如下知識點

  • 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, 而是徹底交給onTouchEventmarkdown

  • 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文檔, 最後纔是羣裏問問ide

----牙叔教程佈局

聲明

部份內容來自網絡 本教程僅用於學習, 禁止用於其餘用途學習

相關文章
相關標籤/搜索