只修列表滚动:每次渲染换一套新的 Table+ScrollPane 塞回同一单元格(复用时 ScrollPane 不重新测量 widget 高度,maxY=0 导致滚轮失效)
This commit is contained in:
1 parent
94c467a40d
commit
ee1f2a2ced
1 file changed
+36
-6
@@ -49,6 +49,11 @@ public final class ObjectPanel {
|
|||||||
java.util.List<Object[]> inspectFields = new ArrayList<Object[]>();
|
java.util.List<Object[]> inspectFields = new ArrayList<Object[]>();
|
||||||
List<Object> objects = new ArrayList<Object>();
|
List<Object> objects = new ArrayList<Object>();
|
||||||
Object target;
|
Object target;
|
||||||
|
Class<?> tableClass;
|
||||||
|
Class<?> scrollClass;
|
||||||
|
Class<?> actorClass;
|
||||||
|
Class<?> cellClass;
|
||||||
|
Object listCell; // 承载列表 ScrollPane 的单元格
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,6 +71,10 @@ public final class ObjectPanel {
|
|||||||
Class<?> skinClass = Class.forName("com.badlogic.gdx.scenes.scene2d.ui.Skin", true, loader);
|
Class<?> skinClass = Class.forName("com.badlogic.gdx.scenes.scene2d.ui.Skin", true, loader);
|
||||||
Class<?> fieldClass = Class.forName("com.badlogic.gdx.scenes.scene2d.ui.TextField", true, loader);
|
Class<?> fieldClass = Class.forName("com.badlogic.gdx.scenes.scene2d.ui.TextField", true, loader);
|
||||||
|
|
||||||
|
state.tableClass = tableClass;
|
||||||
|
state.scrollClass = scrollClass;
|
||||||
|
state.actorClass = actorClass;
|
||||||
|
state.cellClass = cellClass;
|
||||||
Object root = tableClass.getConstructor().newInstance();
|
Object root = tableClass.getConstructor().newInstance();
|
||||||
Object rows = tableClass.getConstructor().newInstance();
|
Object rows = tableClass.getConstructor().newInstance();
|
||||||
call(rows, Obf.TABLE_TOP, new Class<?>[0], tableClass);
|
call(rows, Obf.TABLE_TOP, new Class<?>[0], tableClass);
|
||||||
@@ -116,6 +125,7 @@ public final class ObjectPanel {
|
|||||||
// 唯一 expand+fill 的单元格:内容区(上面是列表/Inspector,最下面是日志块,同一个滚动区)
|
// 唯一 expand+fill 的单元格:内容区(上面是列表/Inspector,最下面是日志块,同一个滚动区)
|
||||||
cell = call(root, Obf.TABLE_ADD, new Class<?>[] {actorClass}, cellClass, scroll);
|
cell = call(root, Obf.TABLE_ADD, new Class<?>[] {actorClass}, cellClass, scroll);
|
||||||
layoutCell(cell, Obf.CELL_TOP, Obf.CELL_EXPAND, Obf.CELL_FILL);
|
layoutCell(cell, Obf.CELL_TOP, Obf.CELL_EXPAND, Obf.CELL_FILL);
|
||||||
|
state.listCell = cell;
|
||||||
|
|
||||||
wire(loader, refresh, new Runnable() {
|
wire(loader, refresh, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -272,8 +282,7 @@ public final class ObjectPanel {
|
|||||||
state.objects = objects;
|
state.objects = objects;
|
||||||
try {
|
try {
|
||||||
// Table.clearChildren()(载荷名 `SourceFile()V`):把列表里的行全清掉重建。
|
// Table.clearChildren()(载荷名 `SourceFile()V`):把列表里的行全清掉重建。
|
||||||
call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class<?>[0], void.class);
|
beginRender(state);
|
||||||
state.logBlockStarted = false;
|
|
||||||
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
||||||
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
||||||
for (int i = 0; i < objects.size() && i < 300; i++) {
|
for (int i = 0; i < objects.size() && i < 300; i++) {
|
||||||
@@ -508,6 +517,29 @@ public final class ObjectPanel {
|
|||||||
* 否则 ScrollPane 里缓存的高度还是旧的,表现为"内容多了却不能滚"。
|
* 否则 ScrollPane 里缓存的高度还是旧的,表现为"内容多了却不能滚"。
|
||||||
* `b_()V` = `invalidate()`(来源:MapMethods 对 gdx-1.11.0 的指纹比对)。
|
* `b_()V` = `invalidate()`(来源:MapMethods 对 gdx-1.11.0 的指纹比对)。
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* 每次渲染都换一套**全新的 Table + ScrollPane**,塞回同一个单元格。
|
||||||
|
*
|
||||||
|
* 为什么必须换:ScrollPane 只在 layout 时量一次里面 widget 的高度,我们之后往 widget 里
|
||||||
|
* 加/删行,它记的高度还是旧的 —— maxY 一直是 0,滚轮就滚不动(你看到的现象)。
|
||||||
|
* 换一个新的 ScrollPane 最省事也最稳(只做这一件事,不改任何别的行为)。
|
||||||
|
*/
|
||||||
|
private static void beginRender(State state) throws Exception {
|
||||||
|
Object table = state.tableClass.getConstructor().newInstance();
|
||||||
|
call(table, Obf.TABLE_TOP, new Class<?>[0], state.tableClass);
|
||||||
|
call(table, Obf.TABLE_LEFT, new Class<?>[0], state.tableClass);
|
||||||
|
Class<?> skinClass = Class.forName("com.badlogic.gdx.scenes.scene2d.ui.Skin", true, state.loader);
|
||||||
|
Object scroll = state.scrollClass.getConstructor(state.actorClass, skinClass)
|
||||||
|
.newInstance(table, state.skin);
|
||||||
|
state.listTable = table;
|
||||||
|
state.listScroll = scroll;
|
||||||
|
if (state.listCell != null) {
|
||||||
|
// Cell.setActor(Actor):把旧 ScrollPane 换成新的
|
||||||
|
call(state.listCell, "D", new Class<?>[] {state.actorClass}, state.cellClass, scroll);
|
||||||
|
}
|
||||||
|
state.logBlockStarted = false;
|
||||||
|
}
|
||||||
|
|
||||||
private static void invalidateList(final State state) {
|
private static void invalidateList(final State state) {
|
||||||
try {
|
try {
|
||||||
call(state.listTable, "b_", new Class<?>[0], void.class);
|
call(state.listTable, "b_", new Class<?>[0], void.class);
|
||||||
@@ -528,8 +560,7 @@ public final class ObjectPanel {
|
|||||||
private static void fillRows(final State state, List<String> lines,
|
private static void fillRows(final State state, List<String> lines,
|
||||||
java.util.Map<Integer, Object[]> clickable) {
|
java.util.Map<Integer, Object[]> clickable) {
|
||||||
try {
|
try {
|
||||||
call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class<?>[0], void.class);
|
beginRender(state);
|
||||||
state.logBlockStarted = false;
|
|
||||||
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
||||||
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
@@ -586,8 +617,7 @@ public final class ObjectPanel {
|
|||||||
/** 用纯文本行填列表区(行不可点)。 */
|
/** 用纯文本行填列表区(行不可点)。 */
|
||||||
private static void fillTextRows(final State state, List<String> lines) {
|
private static void fillTextRows(final State state, List<String> lines) {
|
||||||
try {
|
try {
|
||||||
call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class<?>[0], void.class);
|
beginRender(state);
|
||||||
state.logBlockStarted = false;
|
|
||||||
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
Class<?> cellClass = Class.forName(Obf.CELL, true, state.loader);
|
||||||
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
Class<?> actorClass = Class.forName(Obf.ACTOR, true, state.loader);
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
|
|||||||
Reference in new issue
Block a user