Loading core/java/android/view/ViewStub.java +69 −27 Original line number Diff line number Diff line Loading @@ -142,11 +142,17 @@ public final class ViewStub extends View { * @see #getInflatedId() * @attr ref android.R.styleable#ViewStub_inflatedId */ @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setInflatedIdAsync") public void setInflatedId(@IdRes int inflatedId) { mInflatedId = inflatedId; } /** @hide **/ public Runnable setInflatedIdAsync(@IdRes int inflatedId) { mInflatedId = inflatedId; return null; } /** * Returns the layout resource that will be used by {@link #setVisibility(int)} or * {@link #inflate()} to replace this StubbedView Loading Loading @@ -176,11 +182,17 @@ public final class ViewStub extends View { * @see #inflate() * @attr ref android.R.styleable#ViewStub_layout */ @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setLayoutResourceAsync") public void setLayoutResource(@LayoutRes int layoutResource) { mLayoutResource = layoutResource; } /** @hide **/ public Runnable setLayoutResourceAsync(@LayoutRes int layoutResource) { mLayoutResource = layoutResource; return null; } /** * Set {@link LayoutInflater} to use in {@link #inflate()}, or {@code null} * to use the default. Loading Loading @@ -220,7 +232,7 @@ public final class ViewStub extends View { * @see #inflate() */ @Override @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setVisibilityAsync") public void setVisibility(int visibility) { if (mInflatedViewRef != null) { View view = mInflatedViewRef.get(); Loading @@ -237,32 +249,32 @@ public final class ViewStub extends View { } } /** * Inflates the layout resource identified by {@link #getLayoutResource()} * and replaces this StubbedView in its parent by the inflated layout resource. * * @return The inflated layout resource. * */ public View inflate() { final ViewParent viewParent = getParent(); /** @hide **/ public Runnable setVisibilityAsync(int visibility) { if (visibility == VISIBLE || visibility == INVISIBLE) { ViewGroup parent = (ViewGroup) getParent(); return new ViewReplaceRunnable(inflateViewNoAdd(parent)); } else { return null; } } if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) { final ViewGroup parent = (ViewGroup) viewParent; private View inflateViewNoAdd(ViewGroup parent) { final LayoutInflater factory; if (mInflater != null) { factory = mInflater; } else { factory = LayoutInflater.from(mContext); } final View view = factory.inflate(mLayoutResource, parent, false); final View view = factory.inflate(mLayoutResource, parent, false); if (mInflatedId != NO_ID) { view.setId(mInflatedId); } return view; } private void replaceSelfWithView(View view, ViewGroup parent) { final int index = parent.indexOfChild(this); parent.removeViewInLayout(this); Loading @@ -272,9 +284,25 @@ public final class ViewStub extends View { } else { parent.addView(view, index); } } /** * Inflates the layout resource identified by {@link #getLayoutResource()} * and replaces this StubbedView in its parent by the inflated layout resource. * * @return The inflated layout resource. * */ public View inflate() { final ViewParent viewParent = getParent(); mInflatedViewRef = new WeakReference<View>(view); if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) { final ViewGroup parent = (ViewGroup) viewParent; final View view = inflateViewNoAdd(parent); replaceSelfWithView(view, parent); mInflatedViewRef = new WeakReference<>(view); if (mInflateListener != null) { mInflateListener.onInflate(this, view); } Loading Loading @@ -317,4 +345,18 @@ public final class ViewStub extends View { */ void onInflate(ViewStub stub, View inflated); } /** @hide **/ public class ViewReplaceRunnable implements Runnable { public final View view; ViewReplaceRunnable(View view) { this.view = view; } @Override public void run() { replaceSelfWithView(view, (ViewGroup) getParent()); } } } core/java/android/widget/RemoteViews.java +37 −9 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.view.RemotableViewMethod; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.AdapterView.OnItemClickListener; import com.android.internal.R; Loading Loading @@ -1456,6 +1457,13 @@ public class RemoteViews implements Parcelable, Filter { if (endAction == null) { return ACTION_NOOP; } else { // Special case view stub if (endAction instanceof ViewStub.ViewReplaceRunnable) { root.createTree(); // Replace child tree root.findViewTreeById(viewId).replaceView( ((ViewStub.ViewReplaceRunnable) endAction).view); } return new RunnableAction(endAction); } } Loading Loading @@ -1581,16 +1589,26 @@ public class RemoteViews implements Parcelable, Filter { if ((target == null) || !(target.mRoot instanceof ViewGroup)) { return ACTION_NOOP; } final ViewGroup targetVg = (ViewGroup) target.mRoot; if (nestedViews == null) { // Clear all children when nested views omitted target.mChildren = null; return this; return new RuntimeAction() { @Override public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException { targetVg.removeAllViews(); } }; } else { // Inflate nested views and perform all the async tasks for the child remoteView. final Context context = root.mRoot.getContext(); final AsyncApplyTask task = nestedViews.getAsyncApplyTask( context, (ViewGroup) target.mRoot, null, handler); context, targetVg, null, handler); final ViewTree tree = task.doInBackground(); if (tree == null) { throw new ActionException(task.mError); } // Update the global view tree, so that next call to findViewTreeById // goes through the subtree as well. Loading @@ -1600,10 +1618,8 @@ public class RemoteViews implements Parcelable, Filter { @Override public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException { // This view will exist as we have already made sure final ViewGroup target = (ViewGroup) root.findViewById(viewId); task.onPostExecute(tree); target.addView(task.mResult); targetVg.addView(task.mResult); } }; } Loading Loading @@ -3360,7 +3376,7 @@ public class RemoteViews implements Parcelable, Filter { int count = mRV.mActions.size(); mActions = new Action[count]; for (int i = 0; i < count && !isCancelled(); i++) { // TODO: check if isCanclled in nested views. // TODO: check if isCancelled in nested views. mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler); } } else { Loading Loading @@ -3629,7 +3645,7 @@ public class RemoteViews implements Parcelable, Filter { * and can be searched. */ private static class ViewTree { private final View mRoot; private View mRoot; private ArrayList<ViewTree> mChildren; Loading @@ -3643,7 +3659,7 @@ public class RemoteViews implements Parcelable, Filter { } mChildren = new ArrayList<>(); if (mRoot instanceof ViewGroup && mRoot.isRootNamespace()) { if (mRoot instanceof ViewGroup) { ViewGroup vg = (ViewGroup) mRoot; int count = vg.getChildCount(); for (int i = 0; i < count; i++) { Loading @@ -3668,6 +3684,12 @@ public class RemoteViews implements Parcelable, Filter { return null; } public void replaceView(View v) { mRoot = v; mChildren = null; createTree(); } public View findViewById(int id) { if (mChildren == null) { return mRoot.findViewById(id); Loading @@ -3685,6 +3707,12 @@ public class RemoteViews implements Parcelable, Filter { } private void addViewChild(View v) { // ViewTree only contains Views which can be found using findViewById. // If isRootNamespace is true, this view is skipped. // @see ViewGroup#findViewTraversal(int) if (v.isRootNamespace()) { return; } final ViewTree target; // If the view has a valid id, i.e., if can be found using findViewById, add it to the Loading @@ -3697,7 +3725,7 @@ public class RemoteViews implements Parcelable, Filter { target = this; } if (v instanceof ViewGroup && v.isRootNamespace()) { if (v instanceof ViewGroup) { if (target.mChildren == null) { target.mChildren = new ArrayList<>(); ViewGroup vg = (ViewGroup) v; Loading core/tests/coretests/res/layout/remote_view_host.xml +2 −2 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> android:layout_height="match_parent" /> core/tests/coretests/res/layout/remote_views_text.xml 0 → 100644 +21 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2016 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" /> core/tests/coretests/res/layout/remote_views_viewstub.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2016 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <ViewStub android:id="@+id/viewStub" android:inflatedId="@+id/stub_inflated" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> Loading
core/java/android/view/ViewStub.java +69 −27 Original line number Diff line number Diff line Loading @@ -142,11 +142,17 @@ public final class ViewStub extends View { * @see #getInflatedId() * @attr ref android.R.styleable#ViewStub_inflatedId */ @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setInflatedIdAsync") public void setInflatedId(@IdRes int inflatedId) { mInflatedId = inflatedId; } /** @hide **/ public Runnable setInflatedIdAsync(@IdRes int inflatedId) { mInflatedId = inflatedId; return null; } /** * Returns the layout resource that will be used by {@link #setVisibility(int)} or * {@link #inflate()} to replace this StubbedView Loading Loading @@ -176,11 +182,17 @@ public final class ViewStub extends View { * @see #inflate() * @attr ref android.R.styleable#ViewStub_layout */ @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setLayoutResourceAsync") public void setLayoutResource(@LayoutRes int layoutResource) { mLayoutResource = layoutResource; } /** @hide **/ public Runnable setLayoutResourceAsync(@LayoutRes int layoutResource) { mLayoutResource = layoutResource; return null; } /** * Set {@link LayoutInflater} to use in {@link #inflate()}, or {@code null} * to use the default. Loading Loading @@ -220,7 +232,7 @@ public final class ViewStub extends View { * @see #inflate() */ @Override @android.view.RemotableViewMethod @android.view.RemotableViewMethod(asyncImpl = "setVisibilityAsync") public void setVisibility(int visibility) { if (mInflatedViewRef != null) { View view = mInflatedViewRef.get(); Loading @@ -237,32 +249,32 @@ public final class ViewStub extends View { } } /** * Inflates the layout resource identified by {@link #getLayoutResource()} * and replaces this StubbedView in its parent by the inflated layout resource. * * @return The inflated layout resource. * */ public View inflate() { final ViewParent viewParent = getParent(); /** @hide **/ public Runnable setVisibilityAsync(int visibility) { if (visibility == VISIBLE || visibility == INVISIBLE) { ViewGroup parent = (ViewGroup) getParent(); return new ViewReplaceRunnable(inflateViewNoAdd(parent)); } else { return null; } } if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) { final ViewGroup parent = (ViewGroup) viewParent; private View inflateViewNoAdd(ViewGroup parent) { final LayoutInflater factory; if (mInflater != null) { factory = mInflater; } else { factory = LayoutInflater.from(mContext); } final View view = factory.inflate(mLayoutResource, parent, false); final View view = factory.inflate(mLayoutResource, parent, false); if (mInflatedId != NO_ID) { view.setId(mInflatedId); } return view; } private void replaceSelfWithView(View view, ViewGroup parent) { final int index = parent.indexOfChild(this); parent.removeViewInLayout(this); Loading @@ -272,9 +284,25 @@ public final class ViewStub extends View { } else { parent.addView(view, index); } } /** * Inflates the layout resource identified by {@link #getLayoutResource()} * and replaces this StubbedView in its parent by the inflated layout resource. * * @return The inflated layout resource. * */ public View inflate() { final ViewParent viewParent = getParent(); mInflatedViewRef = new WeakReference<View>(view); if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) { final ViewGroup parent = (ViewGroup) viewParent; final View view = inflateViewNoAdd(parent); replaceSelfWithView(view, parent); mInflatedViewRef = new WeakReference<>(view); if (mInflateListener != null) { mInflateListener.onInflate(this, view); } Loading Loading @@ -317,4 +345,18 @@ public final class ViewStub extends View { */ void onInflate(ViewStub stub, View inflated); } /** @hide **/ public class ViewReplaceRunnable implements Runnable { public final View view; ViewReplaceRunnable(View view) { this.view = view; } @Override public void run() { replaceSelfWithView(view, (ViewGroup) getParent()); } } }
core/java/android/widget/RemoteViews.java +37 −9 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.view.RemotableViewMethod; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.AdapterView.OnItemClickListener; import com.android.internal.R; Loading Loading @@ -1456,6 +1457,13 @@ public class RemoteViews implements Parcelable, Filter { if (endAction == null) { return ACTION_NOOP; } else { // Special case view stub if (endAction instanceof ViewStub.ViewReplaceRunnable) { root.createTree(); // Replace child tree root.findViewTreeById(viewId).replaceView( ((ViewStub.ViewReplaceRunnable) endAction).view); } return new RunnableAction(endAction); } } Loading Loading @@ -1581,16 +1589,26 @@ public class RemoteViews implements Parcelable, Filter { if ((target == null) || !(target.mRoot instanceof ViewGroup)) { return ACTION_NOOP; } final ViewGroup targetVg = (ViewGroup) target.mRoot; if (nestedViews == null) { // Clear all children when nested views omitted target.mChildren = null; return this; return new RuntimeAction() { @Override public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException { targetVg.removeAllViews(); } }; } else { // Inflate nested views and perform all the async tasks for the child remoteView. final Context context = root.mRoot.getContext(); final AsyncApplyTask task = nestedViews.getAsyncApplyTask( context, (ViewGroup) target.mRoot, null, handler); context, targetVg, null, handler); final ViewTree tree = task.doInBackground(); if (tree == null) { throw new ActionException(task.mError); } // Update the global view tree, so that next call to findViewTreeById // goes through the subtree as well. Loading @@ -1600,10 +1618,8 @@ public class RemoteViews implements Parcelable, Filter { @Override public void apply(View root, ViewGroup rootParent, OnClickHandler handler) throws ActionException { // This view will exist as we have already made sure final ViewGroup target = (ViewGroup) root.findViewById(viewId); task.onPostExecute(tree); target.addView(task.mResult); targetVg.addView(task.mResult); } }; } Loading Loading @@ -3360,7 +3376,7 @@ public class RemoteViews implements Parcelable, Filter { int count = mRV.mActions.size(); mActions = new Action[count]; for (int i = 0; i < count && !isCancelled(); i++) { // TODO: check if isCanclled in nested views. // TODO: check if isCancelled in nested views. mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler); } } else { Loading Loading @@ -3629,7 +3645,7 @@ public class RemoteViews implements Parcelable, Filter { * and can be searched. */ private static class ViewTree { private final View mRoot; private View mRoot; private ArrayList<ViewTree> mChildren; Loading @@ -3643,7 +3659,7 @@ public class RemoteViews implements Parcelable, Filter { } mChildren = new ArrayList<>(); if (mRoot instanceof ViewGroup && mRoot.isRootNamespace()) { if (mRoot instanceof ViewGroup) { ViewGroup vg = (ViewGroup) mRoot; int count = vg.getChildCount(); for (int i = 0; i < count; i++) { Loading @@ -3668,6 +3684,12 @@ public class RemoteViews implements Parcelable, Filter { return null; } public void replaceView(View v) { mRoot = v; mChildren = null; createTree(); } public View findViewById(int id) { if (mChildren == null) { return mRoot.findViewById(id); Loading @@ -3685,6 +3707,12 @@ public class RemoteViews implements Parcelable, Filter { } private void addViewChild(View v) { // ViewTree only contains Views which can be found using findViewById. // If isRootNamespace is true, this view is skipped. // @see ViewGroup#findViewTraversal(int) if (v.isRootNamespace()) { return; } final ViewTree target; // If the view has a valid id, i.e., if can be found using findViewById, add it to the Loading @@ -3697,7 +3725,7 @@ public class RemoteViews implements Parcelable, Filter { target = this; } if (v instanceof ViewGroup && v.isRootNamespace()) { if (v instanceof ViewGroup) { if (target.mChildren == null) { target.mChildren = new ArrayList<>(); ViewGroup vg = (ViewGroup) v; Loading
core/tests/coretests/res/layout/remote_view_host.xml +2 −2 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout> android:layout_height="match_parent" />
core/tests/coretests/res/layout/remote_views_text.xml 0 → 100644 +21 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2016 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" />
core/tests/coretests/res/layout/remote_views_viewstub.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2016 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <ViewStub android:id="@+id/viewStub" android:inflatedId="@+id/stub_inflated" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>