牙叔教程 简单易懂
基础下拉框
let arr = [];
for (var i = 0; i < 100; i++) {
arr.push("选项: " + i);
}
let entries = arr.join("|");
ui.layout(
< horizontal >
<button>aaa</button>
<spinner id="mySpinner" textSize="32sp" entries="{{entries}}" />
<button>bbb</button>
</horizontal>
);

选项12下面还有几十个选项
我自己的原则是能用就行, 但是有的人就觉得这个下拉框太长了, 看着不爽, 想把它弄得短一点,
那么应该怎么做?
首先查一下网上的例子, 基本上是这样的
let arr = [];
for (var i = 0; i < 100; i++) {
arr.push("选项: " + i);
}
let entries = arr.join("|");
ui.layout(
<vertical>
<spinner id="mySpinner" textSize="32sp" entries="{{entries}}" spinnerMode="dropdown" />
</vertical>
);
let sp = ui.mySpinner;
let clazz = java .lang.Class.forName("android.widget.Spinner");
let popup = clazz.getDeclaredField("mPopup");
popup.setAccessible(true);
let popupWindow = popup.get(sp);
popupWindow.setHeight(100);
反射获取mPopup字段, 然后获取下拉框 字段名叫mPopup的实例, 再设置他的高度,
你试一下就知道了, 在autojs是不生效的
spinner的下拉框有两种模式, 一种是弹框, 一种是下拉框, 可以通过修改mode来切换
spinnerMode="dropdown"
spinnerMode="dialog"
上面反射修改的就是在 dropdown模式下的下拉框的高度,
dialog模式是没有这个setHeight方法的, 因为会报错
模式在spinner的源码中有说
public Spinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, int mode,
Theme popupTheme) {
...
switch (mode) {
case MODE_DIALOG: {
mPopup = new DialogPopup();
mPopup.setPromptText(a.getString(R.styleable.Spinner_prompt));
break;
}
case MODE_DROPDOWN: {
final DropdownPopup popup = new DropdownPopup(
mPopupContext, attrs, defStyleAttr, defStyleRes);
上面的mPopup就是这个代码里的popup, 也就是那个 new DropdownPopup
那么为什么autojs不能用, 而网上大部分都是这个解决方案呢?
autojs和安卓有啥不一样? 不都是安卓吗?
仔细想想, 还是有不一样的地方,
我们打印一下spinner
com.stardust.autojs.core.ui.widget.JsSpinner{f96a032 VFED..CL. ......I. 0,0-0,0 #1c9}
autojs的spinner是对安卓的spinner的再封装,
popupWindow 也打印一下
let popupWindow = popup.get(sp);
log(popupWindow);
// android.widget.Spinner$DropdownPopup@3ccd85e
这个没问题, 毕竟封装就是继承了Spinner, spinner的继承顺序是:
com.stardust.autojs.core.ui.widget.JsSpinner extends androidx.appcompat.widget.AppCompatSpinner
然后
androidx.appcompat.widget.AppCompatSpinnerextends android.widget.spinner
那么这个私有字段 mPopup 是属于谁的呢?
属于 androidx.appcompat.widget.AppCompatSpinner
我们来验证一下, 这个继承, 如果父子类有同名字段的话, 到底使用谁的值
首先定义一个父类
public class Father {
private String name = "father";
}
再定义一个子类
public class Son extends Father {
private String name = "son";
public void who(){
System.out.println("I am "+name);
}
}
然后创建son实例, 再调用实例的who方法
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
Son son=new Son();
son.who();
}
}

控制台打印的是 I am son
如果子类没有name字段
public class Son extends Father {
public void who(){
System.out.println("I am "+name);
}
}
因为父类的name字段也是private, 所以子类也访问不到, 改成public, 子类此时访问的name字段的值, 就是父类的值

我们来试试修改父类 androidx.appcompat.widget.AppCompatSpinner的mPopup的值, 看看高度能不能改变
"ui";
let arr = [];
for (var i = 0; i < 100; i++) {
arr.push("选项: " + i);
}
let entries = arr.join("|");
ui.layout(
<vertical>
<spinner id="mySpinner" textSize="32sp" entries="{{entries}}" spinnerMode="dropdown" />
</vertical>
);
ui.post(function () {
let sp = ui.mySpinner;
var dcl = context.getClassLoader();
var clazz = dcl.loadClass("androidx.appcompat.widget.AppCompatSpinner");
let popup = clazz.getDeclaredField("mPopup");
popup.setAccessible(true);
let popupWindow = popup.get(sp);
popupWindow.setHeight(300);
}, 300);
一模一样的代码, 除了把15行的类名换成 androidx.appcompat.widget.AppCompatSpinner
这次修改高度就成功了.

这个修改下拉框高度的问题就解决了, 这个解决方案告诉我们, 在把网上的安卓代码改成autojs的时候, 注意autojs是把安卓封装了一层的, 记住这个知识点以后, 就可以避免以后掉进一些坑
环境
雷电模拟器:9.0.17
Android版本: 9
Autojs版本: 9.2.10
名人名言
思路是最重要的, 其他的 百度 , bing , stackoverflow , github, 安卓文档, autojs文档, 最后才是群里问问 — 牙叔教程
声明
部分内容来自网络 本教程仅用于学习, 禁止用于其他用途