Merge "Separate inflate from render step" into nyc-dev
This commit is contained in:
@@ -24,6 +24,7 @@ import com.android.ide.common.rendering.api.RenderSession;
|
|||||||
import com.android.ide.common.rendering.api.Result;
|
import com.android.ide.common.rendering.api.Result;
|
||||||
import com.android.ide.common.rendering.api.Result.Status;
|
import com.android.ide.common.rendering.api.Result.Status;
|
||||||
import com.android.ide.common.rendering.api.SessionParams;
|
import com.android.ide.common.rendering.api.SessionParams;
|
||||||
|
import com.android.layoutlib.bridge.android.RenderParamsFlags;
|
||||||
import com.android.layoutlib.bridge.impl.RenderDrawable;
|
import com.android.layoutlib.bridge.impl.RenderDrawable;
|
||||||
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
|
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
|
||||||
import com.android.layoutlib.bridge.util.DynamicIdMap;
|
import com.android.layoutlib.bridge.util.DynamicIdMap;
|
||||||
@@ -408,7 +409,9 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
|||||||
/**
|
/**
|
||||||
* Starts a layout session by inflating and rendering it. The method returns a
|
* Starts a layout session by inflating and rendering it. The method returns a
|
||||||
* {@link RenderSession} on which further actions can be taken.
|
* {@link RenderSession} on which further actions can be taken.
|
||||||
*
|
* <p/>
|
||||||
|
* If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
|
||||||
|
* this method will only inflate the layout but will NOT render it.
|
||||||
* @param params the {@link SessionParams} object with all the information necessary to create
|
* @param params the {@link SessionParams} object with all the information necessary to create
|
||||||
* the scene.
|
* the scene.
|
||||||
* @return a new {@link RenderSession} object that contains the result of the layout.
|
* @return a new {@link RenderSession} object that contains the result of the layout.
|
||||||
@@ -424,7 +427,10 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
|
|||||||
lastResult = scene.init(params.getTimeout());
|
lastResult = scene.init(params.getTimeout());
|
||||||
if (lastResult.isSuccess()) {
|
if (lastResult.isSuccess()) {
|
||||||
lastResult = scene.inflate();
|
lastResult = scene.inflate();
|
||||||
if (lastResult.isSuccess()) {
|
|
||||||
|
boolean doNotRenderOnCreate = Boolean.TRUE.equals(
|
||||||
|
params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
|
||||||
|
if (lastResult.isSuccess() && !doNotRenderOnCreate) {
|
||||||
lastResult = scene.render(true /*freshRender*/);
|
lastResult = scene.render(true /*freshRender*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ public final class RenderParamsFlags {
|
|||||||
*/
|
*/
|
||||||
public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
|
public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
|
||||||
new Key<Boolean>("xmlFileParser", Boolean.class);
|
new Key<Boolean>("xmlFileParser", Boolean.class);
|
||||||
|
/**
|
||||||
|
* To tell LayoutLib to not render when creating a new session. This allows controlling when the first
|
||||||
|
* layout rendering will happen.
|
||||||
|
*/
|
||||||
|
public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
|
||||||
|
new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
|
||||||
|
|
||||||
// Disallow instances.
|
// Disallow instances.
|
||||||
private RenderParamsFlags() {}
|
private RenderParamsFlags() {}
|
||||||
|
|||||||
@@ -266,6 +266,34 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
mElapsedFrameTimeNanos = nanos;
|
mElapsedFrameTimeNanos = nanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the given view hierarchy to the passed canvas and returns the result of the render
|
||||||
|
* operation.
|
||||||
|
* @param canvas an optional canvas to render the views to. If null, only the measure and
|
||||||
|
* layout steps will be executed.
|
||||||
|
*/
|
||||||
|
private static Result render(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
|
||||||
|
@Nullable Canvas canvas, int width, int height) {
|
||||||
|
// measure again with the size we need
|
||||||
|
// This must always be done before the call to layout
|
||||||
|
measureView(viewRoot, null /*measuredView*/,
|
||||||
|
width, MeasureSpec.EXACTLY,
|
||||||
|
height, MeasureSpec.EXACTLY);
|
||||||
|
|
||||||
|
// now do the layout.
|
||||||
|
viewRoot.layout(0, 0, width, height);
|
||||||
|
handleScrolling(context, viewRoot);
|
||||||
|
|
||||||
|
if (canvas == null) {
|
||||||
|
return SUCCESS.createResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
|
||||||
|
viewRoot.draw(canvas);
|
||||||
|
|
||||||
|
return SUCCESS.createResult();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the scene.
|
* Renders the scene.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -367,24 +395,12 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// measure again with the size we need
|
Result renderResult = SUCCESS.createResult();
|
||||||
// This must always be done before the call to layout
|
|
||||||
measureView(mViewRoot, null /*measuredView*/,
|
|
||||||
mMeasuredScreenWidth, MeasureSpec.EXACTLY,
|
|
||||||
mMeasuredScreenHeight, MeasureSpec.EXACTLY);
|
|
||||||
|
|
||||||
// now do the layout.
|
|
||||||
mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
|
|
||||||
|
|
||||||
handleScrolling(mViewRoot);
|
|
||||||
|
|
||||||
if (params.isLayoutOnly()) {
|
if (params.isLayoutOnly()) {
|
||||||
// delete the canvas and image to reset them on the next full rendering
|
// delete the canvas and image to reset them on the next full rendering
|
||||||
mImage = null;
|
mImage = null;
|
||||||
mCanvas = null;
|
mCanvas = null;
|
||||||
} else {
|
} else {
|
||||||
AttachInfo_Accessor.dispatchOnPreDraw(mViewRoot);
|
|
||||||
|
|
||||||
// draw the views
|
// draw the views
|
||||||
// create the BufferedImage into which the layout will be rendered.
|
// create the BufferedImage into which the layout will be rendered.
|
||||||
boolean newImage = false;
|
boolean newImage = false;
|
||||||
@@ -446,6 +462,9 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
if (mElapsedFrameTimeNanos >= 0) {
|
if (mElapsedFrameTimeNanos >= 0) {
|
||||||
long initialTime = System_Delegate.nanoTime();
|
long initialTime = System_Delegate.nanoTime();
|
||||||
if (!mFirstFrameExecuted) {
|
if (!mFirstFrameExecuted) {
|
||||||
|
// We need to run an initial draw call to initialize the animations
|
||||||
|
render(getContext(), mViewRoot, mCanvas, 0, 0);
|
||||||
|
|
||||||
// The first frame will initialize the animations
|
// The first frame will initialize the animations
|
||||||
Choreographer_Delegate.doFrame(initialTime);
|
Choreographer_Delegate.doFrame(initialTime);
|
||||||
mFirstFrameExecuted = true;
|
mFirstFrameExecuted = true;
|
||||||
@@ -453,14 +472,15 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
// Second frame will move the animations
|
// Second frame will move the animations
|
||||||
Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
|
Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
|
||||||
}
|
}
|
||||||
mViewRoot.draw(mCanvas);
|
renderResult = render(getContext(), mViewRoot, mCanvas, mMeasuredScreenWidth,
|
||||||
|
mMeasuredScreenHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
|
mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
// success!
|
// success!
|
||||||
return SUCCESS.createResult();
|
return renderResult;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// get the real cause of the exception.
|
// get the real cause of the exception.
|
||||||
Throwable t = e;
|
Throwable t = e;
|
||||||
@@ -488,7 +508,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
* @return the measured width/height if measuredView is non-null, null otherwise.
|
* @return the measured width/height if measuredView is non-null, null otherwise.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation") // For the use of Pair
|
@SuppressWarnings("deprecation") // For the use of Pair
|
||||||
private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
|
private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
|
||||||
int width, int widthMode, int height, int heightMode) {
|
int width, int widthMode, int height, int heightMode) {
|
||||||
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
|
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
|
||||||
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
|
int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
|
||||||
@@ -1061,8 +1081,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
* the component supports nested scrolling attempt that first, then use the unconsumed scroll
|
* the component supports nested scrolling attempt that first, then use the unconsumed scroll
|
||||||
* part to scroll the content in the component.
|
* part to scroll the content in the component.
|
||||||
*/
|
*/
|
||||||
private void handleScrolling(View view) {
|
private static void handleScrolling(BridgeContext context, View view) {
|
||||||
BridgeContext context = getContext();
|
|
||||||
int scrollPosX = context.getScrollXPos(view);
|
int scrollPosX = context.getScrollXPos(view);
|
||||||
int scrollPosY = context.getScrollYPos(view);
|
int scrollPosY = context.getScrollYPos(view);
|
||||||
if (scrollPosX != 0 || scrollPosY != 0) {
|
if (scrollPosX != 0 || scrollPosY != 0) {
|
||||||
@@ -1080,7 +1099,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (scrollPosX != 0 || scrollPosY != 0) {
|
if (scrollPosX != 0 || scrollPosY != 0) {
|
||||||
view.scrollBy(scrollPosX, scrollPosY);
|
view.scrollTo(scrollPosX, scrollPosY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1090,7 +1109,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
|
|||||||
ViewGroup group = (ViewGroup) view;
|
ViewGroup group = (ViewGroup) view;
|
||||||
for (int i = 0; i < group.getChildCount(); i++) {
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
View child = group.getChildAt(i);
|
View child = group.getChildAt(i);
|
||||||
handleScrolling(child);
|
handleScrolling(context, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:scrollX="10px"
|
android:scrollX="30px"
|
||||||
android:scrollY="30px">
|
android:scrollY="90px">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
android:layout_width="200dp"
|
android:layout_width="200dp"
|
||||||
android:layout_height="400dp"
|
android:layout_height="400dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:scrollX="-30px"
|
android:scrollX="-90px"
|
||||||
android:scrollY="150px">
|
android:scrollY="450px">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.android.ide.common.resources.configuration.FolderConfiguration;
|
|||||||
import com.android.io.FolderWrapper;
|
import com.android.io.FolderWrapper;
|
||||||
import com.android.layoutlib.bridge.Bridge;
|
import com.android.layoutlib.bridge.Bridge;
|
||||||
import com.android.layoutlib.bridge.android.BridgeContext;
|
import com.android.layoutlib.bridge.android.BridgeContext;
|
||||||
|
import com.android.layoutlib.bridge.android.RenderParamsFlags;
|
||||||
import com.android.layoutlib.bridge.impl.RenderAction;
|
import com.android.layoutlib.bridge.impl.RenderAction;
|
||||||
import com.android.layoutlib.bridge.impl.DelegateManager;
|
import com.android.layoutlib.bridge.impl.DelegateManager;
|
||||||
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
|
import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
|
||||||
@@ -564,7 +565,7 @@ public class Main {
|
|||||||
sFrameworkRepo.getConfiguredResources(config),
|
sFrameworkRepo.getConfiguredResources(config),
|
||||||
themeName, isProjectTheme);
|
themeName, isProjectTheme);
|
||||||
|
|
||||||
return new SessionParams(
|
SessionParams sessionParams = new SessionParams(
|
||||||
layoutParser,
|
layoutParser,
|
||||||
renderingMode,
|
renderingMode,
|
||||||
null /*used for caching*/,
|
null /*used for caching*/,
|
||||||
@@ -574,6 +575,8 @@ public class Main {
|
|||||||
0,
|
0,
|
||||||
targetSdk,
|
targetSdk,
|
||||||
getLayoutLog());
|
getLayoutLog());
|
||||||
|
sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
|
||||||
|
return sessionParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LayoutLog getLayoutLog() {
|
private static LayoutLog getLayoutLog() {
|
||||||
|
|||||||
Reference in New Issue
Block a user