经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
autojs模仿QQ长按弹窗菜单实现示例
来源:jb51  时间:2023/1/28 8:43:12  对本文有异议

分析弹框菜单

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

需求分析

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

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

代码分析

列表怎么写,

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

  1. "nodejs ui";
  2. require("rhino").install();
  3. const ui = require("ui");
  4. class MainActivity extends ui.Activity {
  5. constructor() {
  6. super();
  7. this.items = [];
  8. for (var i = 10; i < 100; i++) {
  9. this.items.push(randomStr(i + 1));
  10. }
  11. }
  12. get layoutXmlFile() {
  13. return "layout.xml";
  14. }
  15. onContentViewSet() {}
  16. }
  17. ui.setMainActivity(MainActivity);

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

  1. <column>
  2. <androidx.recyclerview.widget.RecyclerView id="recyclerView" padding='12' layout_width="match_parent" layout_height="match_parent">
  3. </androidx.recyclerview.widget.RecyclerView>
  4. </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. module.exports=function(recyclerView,items){
  2. await $java.defineClass(TestRecyclerViewViewHolder)
  3. await $java.defineClass(TestRecyclerViewAdapter)
  4. var adapter=new TestRecyclerViewAdapter(items)
  5. recyclerView.setAdapter(adapter)
  6. }

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

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

  1. let definedClass = false;
  2. module.exports = async function (recyclerView, items) {
  3. if (!definedClass) {
  4. await $java.defineClass(TestRecyclerViewViewHolder);
  5. await $java.defineClass(TestRecyclerViewAdapter);
  6. definedClass = true;
  7. }
  8. var adapter = new TestRecyclerViewAdapter(items);
  9. recyclerView.setAdapter(adapter);
  10. };

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

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

  • onCreateViewHolder
  • onBindViewHolder
  • getItemCount
  • getItemViewType

TestRecyclerViewAdapter.js

  1. const ui = require("ui");
  2. class TestRecyclerViewAdapter extends androidx.recyclerview.widget.RecyclerView.Adapter {
  3. constructor(data) {
  4. super();
  5. this.data = data;
  6. }
  7. onCreateViewHolder(parent) {
  8. return new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));
  9. }
  10. onBindViewHolder(holder, position) {
  11. holder.bind(this.data[position], position);
  12. }
  13. getItemCount() {
  14. return this.data.length;
  15. }
  16. getItemViewType() {
  17. return 0;
  18. }
  19. }
  20. module.exports = TestRecyclerViewAdapter;

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

接下来该写TestRecyclerViewViewHolder

  1. class TestRecyclerViewViewHolder extends androidx.recyclerview.widget.RecyclerView.ViewHolder {
  2. constructor(itemView) {
  3. super(itemView);
  4. }
  5. bind(item) {
  6. this.itemView.attr("text", item);
  7. this.item = item;
  8. }
  9. }
  10. module.exports = TestRecyclerViewViewHolder;

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

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

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

长按事件

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

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

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

TestRecyclerViewAdapter.js 中 修改 onCreateViewHolder 方法即可

  1. onCreateViewHolder(parent) {
  2. let testRecyclerViewViewHolder = new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));
  3. testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {
  4. console.log("你长按了我: " + testRecyclerViewViewHolder.item);
  5. return true;
  6. });
  7. return testRecyclerViewViewHolder;
  8. }

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

  1. setLongClick(longClick) {
  2. this.longClick = longClick;
  3. }

相应的修改onCreateViewHolder代码

  1. onCreateViewHolder(parent) {
  2. let testRecyclerViewViewHolder = new TestRecyclerViewViewHolder(ui.inflateXml(parent.getContext(), holderXml, parent));
  3. testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {
  4. this.longClick();
  5. return true;
  6. });
  7. return testRecyclerViewViewHolder;
  8. }

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

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

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

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

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

  1. const ui = require("ui");
  2. const PopupWindow = android.widget.PopupWindow;
  3. const ViewGroup = android.view.ViewGroup;
  4. function showMenuWindow(view) {
  5. let popMenuWindow = ui.inflateXml(
  6. view.getContext(),
  7. `
  8. <column>
  9. <button id="btn1" text="btn1" />
  10. </column>
  11. `,
  12. null
  13. );
  14. let mPopWindow = new PopupWindow(popMenuWindow, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
  15. mPopWindow.setOutsideTouchable(true);
  16. mPopWindow.showAsDropDown(view);
  17. }
  18. module.exports = showMenuWindow;

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

  1. adapter.setLongClick(showMenuWindow);

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

  1. testRecyclerViewViewHolder.itemView.setOnLongClickListener(() => {
  2. this.longClick(testRecyclerViewViewHolder.itemView);
  3. return true;
  4. });

经过测试代码正常运行,

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

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

环境

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

名人名言

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

声明

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

以上就是autojs模仿QQ长按弹窗菜单实现示例的详细内容,更多关于autojs实现QQ长按弹窗菜单的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号