91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

autojs如何實現長按彈窗菜單功能

發布時間:2023-01-28 15:11:12 來源:億速云 閱讀:175 作者:iii 欄目:開發技術

本篇內容主要講解“autojs如何實現長按彈窗菜單功能”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“autojs如何實現長按彈窗菜單功能”吧!

彈窗菜單

由粗到細, 自頂向下的寫代碼

我們現在要修改的文件是showMenuWindow.js

function showMenuWindow(view) {
  let popMenuWindow = ui.inflateXml(
    view.getContext(),
    `
    <column>
    <button id="btn1" text="btn1" />
    </column>
    `,
    null
  );
  let mPopWindow = new PopupWindow(popMenuWindow, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
  mPopWindow.setOutsideTouchable(true);
  mPopWindow.showAsDropDown(view);
}
module.exports = showMenuWindow;

我們先修改xml, QQ的彈窗由兩部分組成

  • 菜單列表

  • 箭頭

因此, xml如下

<column>
  <androidx.recyclerview.widget.RecyclerView id="recyclerView" padding="16" layout_width="match_parent" layout_height="match_parent">
  </androidx.recyclerview.widget.RecyclerView>
  <android.view.View id='arrow' ></android.view.View>
</column>

這給菜單我們用的也是recyclerView, 因此先設置他的adapter, 如果不會就看上一節課程;

function showMenuWindow(view) {
  let popMenuWindow = ui.inflateXml(
    ...
  );
  setPopMenuRecyclerViewAdapter(popMenuWindow.recyclerView, []);
  ...
}

設置Adapter的時候, 第一個參數我們是有的, 第二個參數是adapter要綁定的數據, 現在沒有;

這給菜單數據應該有哪些屬性呢?

  • 菜單顯示的文字

  • 菜單點后的回調函數

因此, 數據大概是這樣的

  menus: [
    {
      name: "復制",
      handle: () => {
        console.log("復制");
      },
    },
    {
      name: "分享",
      handle: () => {
        console.log("分享");
      },
    },
  ],

這種可配置的數據, 我們把它放到config.js中.

數據有了, 接下來我們進入setPopMenuRecyclerViewAdapter方法內部,

setPopMenuRecyclerViewAdapter.js

let definedClass = false;
const PopMenuRecyclerViewViewHolder = require("./PopMenuRecyclerViewViewHolder");
const PopMenuRecyclerViewAdapter = require("./PopMenuRecyclerViewAdapter");
const showMenuWindow = require("../showMenuWindow.js");
module.exports = async function (recyclerView, items) {
  if (!definedClass) {
    await $java.defineClass(PopMenuRecyclerViewViewHolder);
    await $java.defineClass(PopMenuRecyclerViewAdapter);
    definedClass = true;
  }
  var adapter = new PopMenuRecyclerViewAdapter(items);
  adapter.setLongClick(showMenuWindow);
  recyclerView.setAdapter(adapter);
};

基本上就是復制黏貼, 修改一下類名即可

PopMenuRecyclerViewAdapter.js中, 修改一下holderXml即可

PopMenuRecyclerViewViewHolder.js, bind需要修改

bind(item) {
  this.itemView.attr("text", item);
  this.item = item;
}

除了設置adapter, 菜單彈框還需要設置layoutManager, 這樣我們可以控制水平方向上菜單的數量

const layoutManager = new androidx.recyclerview.widget.GridLayoutManager(this, 5);
grid.setLayoutManager(layoutManager);

先設置layoutManager, 再設置adapter

PopMenuRecyclerViewViewHolder.js, 需要修改一下bind方法, 他的item是對象, 文本是item.name

bind(item) {
  this.itemView.attr("text", item.name);
  this.item = item;
}

運行代碼, 看看效果

autojs如何實現長按彈窗菜單功能

菜單出來了, 接著寫箭頭, 菜單的xml是

<column>
  <androidx.recyclerview.widget.RecyclerView id="recyclerView" padding="16" layout_width="match_parent" layout_height="match_parent">
  </androidx.recyclerview.widget.RecyclerView>
  <android.view.View id='arrow' ></android.view.View>
</column>

下面那個View就是我們放箭頭的地方

箭頭

箭頭可能指向上方, 也可能指向下方, 我們通過設置View的前景, 來展示箭頭

arrowView.setForeground(drawable);

這里我們要寫自己的drawable, 因此, 要繼承

class TriangleDrawable extends android.graphics.drawable.Drawable {}

重寫他的draw方法

draw(canvas) {
  canvas.drawPath(this.path, paint);
}

畫筆創建一支就好, 因為沒有發現要創建多支畫筆的需求, 以后需要再改, 滿足當下即可;

path肯定夠是變的, 因為箭頭有上下兩個位置;

那么在這個TriangleDrawable類中, 我們要實現那些東西呢?

  • 設置箭頭方向 setDirection

  • 目前想不到別的了

如何確認箭頭方向?

假設列表有ABC三條數據, ABC依次排列, 在A的頂部, 如果有控件繼續放置一條數據D的話,

那么我們就把彈框菜單放到A的頂部, 如果沒有, 就放到A的底部

怎么判斷是否有足夠的空間放下D數據呢? 和那些東西有關?

  • 被長按的view的頂部坐標

  • 彈框菜單的高度

有這兩個信息, 我們就可以判斷箭頭的方向了.

為了判斷箭頭方向, 我們新建一個文件, getArrowDirection.js, 文件夾名popMenuRecyclerView, 和箭頭明顯不合適, 因此我們新建文件夾popMenuArrow

被長按的view的頂部坐標

view.getTop()

彈框菜單的高度, 因為彈框還沒有顯示出來, 所以我們要預先測量他的高度

popWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
let popupWindowHeight = popWindow.getContentView().getMeasuredHeight()

判斷箭頭指向

  if (longClickedViewTop - popupWindowHeight < 0) {
    // 上面放不下了, 菜單在下面出現, 箭頭指向上方
    return "up";
  } else {
    return "down";
  }

我們給箭頭一個背景色, 先看當前的效果

autojs如何實現長按彈窗菜單功能

autojs如何實現長按彈窗菜單功能

可以看到箭頭上下的效果已經出來了,

箭頭View的挪動使用了addView和removeView

let arrowView = popMenuWindow.findView("arrow");
popMenuWindow.findView("root").removeView(arrowView);
popMenuWindow.findView("root").addView(arrowView, 0);

這里有個問題, 箭頭的背景色為什么那么長, 是彈框菜單的兩倍多.

這是因為GridLayoutManager第二個參數設置了5, 我們改為Math.min, 取最小值, 寬度問題就符合預期了

const layoutManager = new GridLayoutManager(view.getContext(), Math.min(popMenus.length, 5));

調整popwindow的位置

如果彈框菜單在長按控件的上方, 那么應該偏移多少?

Y軸偏移量 = 彈框菜單的高度 + 長按控件的高度

調用方法如下

    let offset = popMenuCalculateOffset(view, mPopWindow, arrowDirection);
    if (arrowDirection == "down") {
      console.log("箭頭朝下");
      mPopWindow.showAsDropDown(view, offset.x, offset.y);
    }

我們新建一個文件 popMenuCalculateOffset.js

module.exports = function popMenuCalculateOffset(longClickedView, popWindow, arrowDirection) {
  let contentView = popWindow.getContentView();
  let width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
  let height = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
  contentView.measure(width, height);
  popWindow.setBackgroundDrawable(new ColorDrawable(0));
  let contentViewHeight = contentView.getMeasuredHeight();
  let longClickedViewHeight = longClickedView.getHeight();
  console.log("contentViewHeight = " + contentViewHeight);
  if (arrowDirection == "down") {
    let y = contentViewHeight + longClickedViewHeight;
    return { x: 0, y: -y };
  } else {
    return { x: 0, y: 0 };
  }
};

獲取高寬高以后, 我們的

    let offset = popMenuCalculateOffset(view, mPopWindow, arrowDirection);
    if (arrowDirection == "down") {
      console.log("箭頭朝下");
      mPopWindow.showAsDropDown(view, offset.x, offset.y);
    } else {
      let arrowView = popMenuWindow.findView("arrow");
      popMenuWindow.findView("root").removeView(arrowView);
      popMenuWindow.findView("root").addView(arrowView, 0);
      mPopWindow.showAsDropDown(view, offset.x, offset.y);
    }

代碼寫了不少了, 看看效果, 及時排查bug

箭頭朝上

autojs如何實現長按彈窗菜單功能

箭頭朝下

autojs如何實現長按彈窗菜單功能

繪制箭頭

我們用canvas畫個三角形, 首先我們要繼承類, 重寫他的draw方法

class TriangleDrawable extends android.graphics.drawable.Drawable {}

單獨寫一個類文件 TriangleDrawable.js, 放到文件夾 popMenuArrow;

繪制箭頭之前, 要知道箭頭的寬高, 和箭頭的中點;

  • 箭頭的寬高, 我們就用arrowView的高度;

  • 箭頭的中點, 我們指向被長按的控件 X 軸的中心

為了使類, 盡可能的比較純, 我們傳遞的參數選擇具體的數值, 而不是控件;

這里的純指的是沒有副作用, 以及可復用的程度

class TriangleDrawable extends android.graphics.drawable.Drawable {
  setHeight(height) {
    this.height = height;
  }
  setWidth(width) {
    this.width = width;
  }
  setDirection(direction) {
    this.direction = direction;
  }
  setColor(color) {
    this.color = Color.parse(color).value;
  }
  setLongClickedViewWidth(longClickedViewWidth) {
    this.longClickedViewWidth = longClickedViewWidth;
  }
  draw(canvas) {
    trianglePath.reset();
    if (this.direction == "down") {
      console.log("down");
      trianglePath.moveTo(this.width / 2, this.height);
      trianglePath.lineTo(this.width / 2 - this.height / 2, 0);
      trianglePath.lineTo(this.width / 2 + this.height / 2, 0);
    } else {
      trianglePath.moveTo(this.width / 2, 0);
      trianglePath.lineTo(this.width / 2 - this.height / 2, this.height);
      trianglePath.lineTo(this.width / 2 + this.height / 2, this.height);
    }
    trianglePath.close();
    canvas.drawPath(trianglePath, paint);
  }
}
module.exports = TriangleDrawable;

在popupWindow出現之前, 我們要把箭頭繪制出來,

await setArrowForeground(arrow, arrowDirection, view);
mPopWindow.showAsDropDown(view, offset.x, offset.y);

使用onPreDraw, 在繪制之前, 我們可以獲取到正確的寬高

  arrow.getViewTreeObserver().addOnPreDrawListener(
    new android.view.ViewTreeObserver.OnPreDrawListener({
      onPreDraw: function () {
        arrow.getViewTreeObserver().removeOnPreDrawListener(this);
        let arrowHeight = arrow.getHeight();
        let arrowWidth = arrow.getWidth();
        triangleDrawable.setWidth(arrowWidth);
        triangleDrawable.setHeight(arrowHeight);
        arrow.setForeground(triangleDrawable);
        return true;
      },
    })
  );

代碼寫了不少了, 先測試一下效果

箭頭朝上

autojs如何實現長按彈窗菜單功能

箭頭朝下

autojs如何實現長按彈窗菜單功能

修改顏色和圓角

顏色這個就不多說了, 非常容易修改, 說下圓角

修改圓角是在這個文件中: showMenuWindow.js, 我們要給RecyclerView包裹一層card

<card cardCornerRadius="8dp" w='wrap_content'>
...
</card>

autojs如何實現長按彈窗菜單功能

給彈框菜單添加點擊事件

也就是給彈框菜單中的recyclerview添加點擊事件

增加點擊事件所在的文件是 popMenuRecyclerView/PopMenuRecyclerViewAdapter.js,

我們修改他的onCreateViewHolder

onCreateViewHolder(parent) {
  let testRecyclerViewViewHolder = new PopMenuRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));
  testRecyclerViewViewHolder.itemView.setOnClickListener(() => {
    let item = this.data[testRecyclerViewViewHolder.getAdapterPosition()];
    item.handle();
    return true;
  });
  return testRecyclerViewViewHolder;
}

點擊事件生效了, 還有個問題, 點擊了之后,彈框菜單沒有消失, 我們在這里又引用不到彈框實例, 怎么弄?

彈框菜單點擊事件引用彈框實例

我們可以用全局對象, 掛載彈框的實例;

我們不選怎全局對象, 而是去能引用的地方引用實例;

在 showMenuWindow.js 這個文件中, 出現了popupWindow實例, 我們把這個實例作為參數, 傳遞給

setPopMenuRecyclerViewAdapter

setPopMenuRecyclerViewAdapter(mPopWindow, grid, popMenus);

setPopMenuRecyclerViewAdapter.js

module.exports = async function (mPopWindow, recyclerView, items) {
  const menuClick = (item, itemView) => {
    console.log(itemView);
    item.handle();
    mPopWindow.dismiss();
  };
  var adapter = new PopMenuRecyclerViewAdapter(items);
  adapter.setClick(menuClick);
  recyclerView.setAdapter(adapter);
};

我們在這個文件中給adapter設置了點擊事件, 相應的要在 PopMenuRecyclerViewAdapter.js 文件中添加方法,

setClick

class PopMenuRecyclerViewAdapter extends androidx.recyclerview.widget.RecyclerView.Adapter {
  constructor(data) {
    super();
    this.data = data;
    this.click = () => {};
  }
  onCreateViewHolder(parent) {
    let testRecyclerViewViewHolder = new PopMenuRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));
    testRecyclerViewViewHolder.itemView.setOnClickListener(() => {
      let item = this.data[testRecyclerViewViewHolder.getAdapterPosition()];
      this.click(item, testRecyclerViewViewHolder.itemView);
      return true;
    });
    return testRecyclerViewViewHolder;
  }
  ...
  setClick(click) {
    this.click = click;
  }
}
module.exports = PopMenuRecyclerViewAdapter;

如果要增加多個菜單, 在config.js中修改配置即可

autojs如何實現長按彈窗菜單功能

到此,相信大家對“autojs如何實現長按彈窗菜單功能”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

上饶市| 师宗县| 潞城市| 阜城县| 洛阳市| 阆中市| 江安县| 金溪县| 孟州市| 右玉县| 南汇区| 娄底市| 乌兰察布市| 枞阳县| 历史| 万州区| 淮南市| 朝阳区| 淮阳县| 赣榆县| 丹巴县| 海门市| 禄丰县| 临武县| 玉树县| 岱山县| 淅川县| 安义县| 紫金县| 论坛| 西贡区| 平泉县| 高阳县| 平果县| 哈密市| 苗栗县| 竹北市| 营山县| 裕民县| 安福县| 五台县|