diff --git a/viewpanel/src/com/spineview/ObjectPanel.java b/viewpanel/src/com/spineview/ObjectPanel.java index e8adfd7..ec5e94e 100644 --- a/viewpanel/src/com/spineview/ObjectPanel.java +++ b/viewpanel/src/com/spineview/ObjectPanel.java @@ -49,6 +49,11 @@ public final class ObjectPanel { java.util.List inspectFields = new ArrayList(); List objects = new ArrayList(); 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 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 rows = tableClass.getConstructor().newInstance(); call(rows, Obf.TABLE_TOP, new Class[0], tableClass); @@ -116,6 +125,7 @@ public final class ObjectPanel { // 唯一 expand+fill 的单元格:内容区(上面是列表/Inspector,最下面是日志块,同一个滚动区) cell = call(root, Obf.TABLE_ADD, new Class[] {actorClass}, cellClass, scroll); layoutCell(cell, Obf.CELL_TOP, Obf.CELL_EXPAND, Obf.CELL_FILL); + state.listCell = cell; wire(loader, refresh, new Runnable() { @Override @@ -272,8 +282,7 @@ public final class ObjectPanel { state.objects = objects; try { // Table.clearChildren()(载荷名 `SourceFile()V`):把列表里的行全清掉重建。 - call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class[0], void.class); - state.logBlockStarted = false; + beginRender(state); Class cellClass = Class.forName(Obf.CELL, true, state.loader); Class actorClass = Class.forName(Obf.ACTOR, true, state.loader); for (int i = 0; i < objects.size() && i < 300; i++) { @@ -508,6 +517,29 @@ public final class ObjectPanel { * 否则 ScrollPane 里缓存的高度还是旧的,表现为"内容多了却不能滚"。 * `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) { try { 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 lines, java.util.Map clickable) { try { - call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class[0], void.class); - state.logBlockStarted = false; + beginRender(state); Class cellClass = Class.forName(Obf.CELL, true, state.loader); Class actorClass = Class.forName(Obf.ACTOR, true, state.loader); for (int i = 0; i < lines.size(); i++) { @@ -586,8 +617,7 @@ public final class ObjectPanel { /** 用纯文本行填列表区(行不可点)。 */ private static void fillTextRows(final State state, List lines) { try { - call(state.listTable, Obf.TABLE_CLEAR_CHILDREN, new Class[0], void.class); - state.logBlockStarted = false; + beginRender(state); Class cellClass = Class.forName(Obf.CELL, true, state.loader); Class actorClass = Class.forName(Obf.ACTOR, true, state.loader); for (String line : lines) {