广告位联系
返回顶部
分享到

autojs模仿QQ长按弹窗菜单实现示例(一)

Android 来源:互联网 作者:佚名 发布时间:2023-01-28 14:01:45 人浏览
摘要

分析弹框菜单 圆角 列表, 类似grid 箭头位于文字中间上(下)方 需求分析 如果要写一个这样的教程, 我们需要做什么 写一个列表, 用来触发长按选项 写一个弹窗菜单 代码分析 列表怎么写

分析弹框菜单

  • 圆角
  • 列表, 类似grid
  • 箭头位于文字中间上(下)方

需求分析

如果要写一个这样的教程, 我们需要做什么

  • 写一个列表, 用来触发长按选项
  • 写一个弹窗菜单

代码分析

列表怎么写,

先来一个最简单的布局代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

"nodejs ui";

require("rhino").install();

const ui = require("ui");

class MainActivity extends ui.Activity {

  constructor() {

    super();

    this.items = [];

    for (var i = 10; i < 100; i++) {

      this.items.push(randomStr(i + 1));

    }

  }

  get layoutXmlFile() {

    return "layout.xml";

  }

  onContentViewSet() {}

}

ui.setMainActivity(MainActivity);

layout.xml文件内容, 就一个recyclerview

1

2

3

4

<column>

    <androidx.recyclerview.widget.RecyclerView id="recyclerView" padding='12' layout_width="match_parent" layout_height="match_parent">

    </androidx.recyclerview.widget.RecyclerView>

</column>

RecyclerView基础代码

在onContentViewSet这个方法中, 我们去写列表, 列表设置adapter即可;

我们要创建自己的Adapter类, 继承自RecyclerView.Adapter

1

class MyAdapter extends androidx.recyclerview.widget.RecyclerView.Adapter {}

这里用MyAdapter命名合适吗? 不合适, 如果你以后也用了MyAdapter, 那么可能造成类名冲突, 所以, 我们改个名字, 我们是在测试, 因此就叫 TestReayclerViewAdapter,

还有一点是, 因为我们要写两个类, 还有一个文件实例化两个类, 因此我们把这个三个文件放到同一个文件夹

我们自顶向下来写代码, 首先我们写的是setTestRecyclerViewAdapter.js, 他这个里面要做几件事:

  • 加载两个类, Adapter和Holder, Holder先加载, 因为他会在Adapter中使用
  • 实例化两个类

类呢, 我们先不写, 我们先写伪代码

setTestRecyclerViewAdapter.js

1

2

3

4

5

6

module.exports=function(recyclerView,items){

  await $java.defineClass(TestRecyclerViewViewHolder)

  await $java.defineClass(TestRecyclerViewAdapter)

  var adapter=new TestRecyclerViewAdapter(items)

  recyclerView.setAdapter(adapter)

}

这样写怎么样, 有问题吗?

有问题, 如果每次都defineClass, 那么就会报错, 重复定义类, 因此, 我们设置个flag, 类只定义一次

1

2

3

4

5

6

7

8

9

10

let definedClass = false;

module.exports = async function (recyclerView, items) {

  if (!definedClass) {

    await $java.defineClass(TestRecyclerViewViewHolder);

    await $java.defineClass(TestRecyclerViewAdapter);

    definedClass = true;

  }

  var adapter = new TestRecyclerViewAdapter(items);

  recyclerView.setAdapter(adapter);

};

这样就没问题了, 接下来我们写TestRecyclerViewAdapter, 为什么先写他呢, 前面说过了, 我们是自顶向下写,

TestRecyclerViewAdapter里面要写什么呢? 重写三个方法

  • onCreateViewHolder
  • onBindViewHolder
  • getItemCount
  • getItemViewType
  •  

TestRecyclerViewAdapter.js

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

const ui = require("ui");

class TestRecyclerViewAdapter extends androidx.recyclerview.widget.RecyclerView.Adapter {

  constructor(data) {

    super();

    this.data = data;

  }

  onCreateViewHolder(parent) {

    return new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));

  }

  onBindViewHolder(holder, position) {

    holder.bind(this.data[position], position);

  }

  getItemCount() {

    return this.data.length;

  }

  getItemViewType() {

    return 0;

  }

}

module.exports = TestRecyclerViewAdapter;

这个代码里面, 唯一需要变动的地方是holderXml

接下来该写TestRecyclerViewViewHolder

1

2

3

4

5

6

7

8

9

10

class TestRecyclerViewViewHolder extends androidx.recyclerview.widget.RecyclerView.ViewHolder {

  constructor(itemView) {

    super(itemView);

  }

  bind(item) {

    this.itemView.attr("text", item);

    this.item = item;

  }

}

module.exports = TestRecyclerViewViewHolder;

到这里为止, 一个recyclerview的骨架就成型了, 先看看效果

最简单的列表就是如此, 我们给他润色一下, 字体放大, 再加个圆角背景

列表有了, 接下来我们要考虑弹框的事情了, 那么第一个考虑的点就是, 长按事件

长按事件

长按事件在哪个文件写呢?

我们既可以在Adapter中写, 也可以在Holder中写,

如果在Holder中写, 那么我们就要把长按的方法, 从Adapter传给Holder, 我们需要多写几个字幕母, 因此我选择在Adapter中写长按事件

TestRecyclerViewAdapter.js 中 修改 onCreateViewHolder 方法即可

1

2

3

4

5

6

7

8

onCreateViewHolder(parent) {

  let testRecyclerViewViewHolder = new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));

  testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {

    console.log("你长按了我: " + testRecyclerViewViewHolder.item);

    return true;

  });

  return testRecyclerViewViewHolder;

}

长按事件可能是多种多样的, 因此, 我们在TestRecyclerViewAdapter.js中, 增加一个方法setLongClick

1

2

3

setLongClick(longClick) {

  this.longClick = longClick;

}

相应的修改onCreateViewHolder代码

1

2

3

4

5

6

7

8

onCreateViewHolder(parent) {

  let testRecyclerViewViewHolder = new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));

  testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {

    this.longClick();

    return true;

  });

  return testRecyclerViewViewHolder;

}

setTestRecyclerViewAdapter.js中的代码要添加一行

1

adapter.setLongClick(() => console.log("this is long click"));

代码修改了一些以后, 就应该测试一下, 测试正常以后, 再进行下一步操作, 小幅迭代

点击后出现弹框, 我们先不管菜单, 先弹个框出来

我们创建一个文件: showMenuWindow.js

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

const ui = require("ui");

const PopupWindow = android.widget.PopupWindow;

const ViewGroup = android.view.ViewGroup;

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;

然后在setTestRecyclerViewAdapter.js文件中调用他

1

adapter.setLongClick(showMenuWindow);

因此showMenuWindow有一个参数view, 就是你长按的那个view, 所以我们还要去Adapter中修改setLongClick

1

2

3

4

testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {

  this.longClick(testRecyclerViewViewHolder.itemView);

  return true;

});

经过测试代码正常运行,

接下来呢, 是把这个弹框改成菜单的样式,

今天先写到这里, 下一个教程继续

环境

设备: 小米11pro
Android版本: 12
Autojs版本: 9.3.11

名人名言

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

声明

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


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7191457876626374693
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计