Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3366cb2a authored by Adam Cohen's avatar Adam Cohen Committed by Android (Google) Code Review
Browse files

Merge "Adding simple ArrayList API for collection widgets"

parents 6fd651eb 50f3d1ba
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -29081,6 +29081,7 @@ package android.widget {
    method public void setRelativeScrollPosition(int, int);
    method public deprecated void setRemoteAdapter(int, int, android.content.Intent);
    method public void setRemoteAdapter(int, android.content.Intent);
    method public void setRemoteAdapter(int, java.util.ArrayList<android.widget.RemoteViews>);
    method public void setScrollPosition(int, int);
    method public void setShort(int, java.lang.String, short);
    method public void setString(int, java.lang.String, java.lang.String);
+114 −15
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;


/**
 * A class that describes a view hierarchy that can be displayed in
 * another process. The hierarchy is inflated from a layout resource
@@ -340,7 +339,7 @@ public class RemoteViews implements Parcelable, Filter {
            if (target == null) return;

            if (!mIsWidgetCollectionChild) {
                Log.e("RemoteViews", "The method setOnClickFillInIntent is available " +
                Log.e(LOG_TAG, "The method setOnClickFillInIntent is available " +
                        "only from RemoteViewsFactory (ie. on collection items).");
                return;
            }
@@ -359,13 +358,13 @@ public class RemoteViews implements Parcelable, Filter {
                        if (parent instanceof AppWidgetHostView || parent == null) {
                            // Somehow they've managed to get this far without having
                            // and AdapterView as a parent.
                            Log.e("RemoteViews", "Collection item doesn't have AdapterView parent");
                            Log.e(LOG_TAG, "Collection item doesn't have AdapterView parent");
                            return;
                        }

                        // Insure that a template pending intent has been set on an ancestor
                        if (!(parent.getTag() instanceof PendingIntent)) {
                            Log.e("RemoteViews", "Attempting setOnClickFillInIntent without" +
                            Log.e(LOG_TAG, "Attempting setOnClickFillInIntent without" +
                                    " calling setPendingIntentTemplate on parent.");
                            return;
                        }
@@ -472,7 +471,7 @@ public class RemoteViews implements Parcelable, Filter {
                av.setOnItemClickListener(listener);
                av.setTag(pendingIntentTemplate);
            } else {
                Log.e("RemoteViews", "Cannot setPendingIntentTemplate on a view which is not" +
                Log.e(LOG_TAG, "Cannot setPendingIntentTemplate on a view which is not" +
                        "an AdapterView (id: " + viewId + ")");
                return;
            }
@@ -487,6 +486,84 @@ public class RemoteViews implements Parcelable, Filter {
        public final static int TAG = 8;
    }

    private class SetRemoteViewsAdapterList extends Action {
        public SetRemoteViewsAdapterList(int id, ArrayList<RemoteViews> list) {
            this.viewId = id;
            this.list = list;
        }

        public SetRemoteViewsAdapterList(Parcel parcel) {
            viewId = parcel.readInt();
            int count = parcel.readInt();
            list = new ArrayList<RemoteViews>();

            for (int i = 0; i < count; i++) {
                RemoteViews rv = RemoteViews.CREATOR.createFromParcel(parcel);
                list.add(rv);
            }
        }

        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(TAG);
            dest.writeInt(viewId);

            if (list == null || list.size() == 0) {
                dest.writeInt(0);
            } else {
                int count = list.size();
                dest.writeInt(count);
                for (int i = 0; i < count; i++) {
                    RemoteViews rv = list.get(i);
                    rv.writeToParcel(dest, flags);
                }
            }
        }

        @Override
        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
            final View target = root.findViewById(viewId);
            if (target == null) return;

            // Ensure that we are applying to an AppWidget root
            if (!(rootParent instanceof AppWidgetHostView)) {
                Log.e(LOG_TAG, "SetRemoteViewsAdapterIntent action can only be used for " +
                        "AppWidgets (root id: " + viewId + ")");
                return;
            }
            // Ensure that we are calling setRemoteAdapter on an AdapterView that supports it
            if (!(target instanceof AbsListView) && !(target instanceof AdapterViewAnimator)) {
                Log.e(LOG_TAG, "Cannot setRemoteViewsAdapter on a view which is not " +
                        "an AbsListView or AdapterViewAnimator (id: " + viewId + ")");
                return;
            }

            if (target instanceof AbsListView) {
                AbsListView v = (AbsListView) target;
                Adapter a = v.getAdapter();
                if (a instanceof RemoteViewsListAdapter) {
                    ((RemoteViewsListAdapter) a).setViewsList(list);
                } else {
                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list));
                }
            } else if (target instanceof AdapterViewAnimator) {
                AdapterViewAnimator v = (AdapterViewAnimator) target;
                Adapter a = v.getAdapter();
                if (a instanceof RemoteViewsListAdapter) {
                    ((RemoteViewsListAdapter) a).setViewsList(list);
                } else {
                    v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list));
                }
            }
        }

        public String getActionName() {
            return "SetRemoteViewsAdapterList";
        }

        ArrayList<RemoteViews> list;
        public final static int TAG = 15;
    }

    private class SetRemoteViewsAdapterIntent extends Action {
        public SetRemoteViewsAdapterIntent(int id, Intent intent) {
            this.viewId = id;
@@ -511,13 +588,13 @@ public class RemoteViews implements Parcelable, Filter {

            // Ensure that we are applying to an AppWidget root
            if (!(rootParent instanceof AppWidgetHostView)) {
                Log.e("RemoteViews", "SetRemoteViewsAdapterIntent action can only be used for " +
                Log.e(LOG_TAG, "SetRemoteViewsAdapterIntent action can only be used for " +
                        "AppWidgets (root id: " + viewId + ")");
                return;
            }
            // Ensure that we are calling setRemoteAdapter on an AdapterView that supports it
            if (!(target instanceof AbsListView) && !(target instanceof AdapterViewAnimator)) {
                Log.e("RemoteViews", "Cannot setRemoteViewsAdapter on a view which is not " +
                Log.e(LOG_TAG, "Cannot setRemoteViewsAdapter on a view which is not " +
                        "an AbsListView or AdapterViewAnimator (id: " + viewId + ")");
                return;
            }
@@ -585,7 +662,7 @@ public class RemoteViews implements Parcelable, Filter {
            // If the view is an AdapterView, setting a PendingIntent on click doesn't make much
            // sense, do they mean to set a PendingIntent template for the AdapterView's children?
            if (mIsWidgetCollectionChild) {
                Log.w("RemoteViews", "Cannot setOnClickPendingIntent for collection item " +
                Log.w(LOG_TAG, "Cannot setOnClickPendingIntent for collection item " +
                        "(id: " + viewId + ")");
                ApplicationInfo appInfo = root.getContext().getApplicationInfo();

@@ -772,7 +849,7 @@ public class RemoteViews implements Parcelable, Filter {
            try {
                //noinspection ConstantIfStatement
                if (false) {
                    Log.d("RemoteViews", "view: " + klass.getName() + " calling method: "
                    Log.d(LOG_TAG, "view: " + klass.getName() + " calling method: "
                        + this.methodName + "()");
                }
                method.invoke(view);
@@ -945,7 +1022,7 @@ public class RemoteViews implements Parcelable, Filter {
            this.type = in.readInt();
            //noinspection ConstantIfStatement
            if (false) {
                Log.d("RemoteViews", "read viewId=0x" + Integer.toHexString(this.viewId)
                Log.d(LOG_TAG, "read viewId=0x" + Integer.toHexString(this.viewId)
                        + " methodName=" + this.methodName + " type=" + this.type);
            }

@@ -1012,7 +1089,7 @@ public class RemoteViews implements Parcelable, Filter {
            out.writeInt(this.type);
            //noinspection ConstantIfStatement
            if (false) {
                Log.d("RemoteViews", "write viewId=0x" + Integer.toHexString(this.viewId)
                Log.d(LOG_TAG, "write viewId=0x" + Integer.toHexString(this.viewId)
                        + " methodName=" + this.methodName + " type=" + this.type);
            }

@@ -1139,7 +1216,7 @@ public class RemoteViews implements Parcelable, Filter {
            try {
                //noinspection ConstantIfStatement
                if (false) {
                    Log.d("RemoteViews", "view: " + klass.getName() + " calling method: "
                    Log.d(LOG_TAG, "view: " + klass.getName() + " calling method: "
                        + this.methodName + "(" + param.getName() + ") with "
                        + (this.value == null ? "null" : this.value.getClass().getName()));
                }
@@ -1562,6 +1639,9 @@ public class RemoteViews implements Parcelable, Filter {
                    case BitmapReflectionAction.TAG:
                        mActions.add(new BitmapReflectionAction(parcel));
                        break;
                    case SetRemoteViewsAdapterList.TAG:
                        mActions.add(new SetRemoteViewsAdapterList(parcel));
                        break;
                    default:
                        throw new ActionException("Tag " + tag + " not found");
                    }
@@ -1978,11 +2058,11 @@ public class RemoteViews implements Parcelable, Filter {
    }

    /**
     * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
     * Equivalent to calling {@link android.widget.AdapterView#setRemoteViewsAdapter(Intent)}.
     *
     * @param appWidgetId The id of the app widget which contains the specified view. (This
     *      parameter is ignored in this deprecated method)
     * @param viewId The id of the {@link AbsListView}
     * @param viewId The id of the {@link AdapterView}
     * @param intent The intent of the service which will be
     *            providing data to the RemoteViewsAdapter
     * @deprecated This method has been deprecated. See
@@ -1997,7 +2077,7 @@ public class RemoteViews implements Parcelable, Filter {
     * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
     * Can only be used for App Widgets.
     *
     * @param viewId The id of the {@link AbsListView}
     * @param viewId The id of the {@link AdapterView}
     * @param intent The intent of the service which will be
     *            providing data to the RemoteViewsAdapter
     */
@@ -2005,6 +2085,25 @@ public class RemoteViews implements Parcelable, Filter {
        addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
    }

    /**
     * Creates a simple Adapter for the viewId specified. The viewId must point to an AdapterView,
     * ie. {@link ListView}, {@link GridView}, {@link StackView} or {@link AdapterViewAnimator}.
     * This is a simpler but less flexible approach to populating collection widgets. Its use is
     * encouraged for most scenarios, as long as the total memory within the list of RemoteViews
     * is relatively small (ie. doesn't contain large or numerous Bitmaps, see {@link
     * RemoteViews#setImageViewBitmap}). In the case of numerous images, the use of API is still
     * possible by setting image URIs instead of Bitmaps, see {@link RemoteViews#setImageViewUri}.
     *
     * This API is supported in the compatibility library for previous API levels, see
     * RemoteViewsCompat.
     *
     * @param viewId The id of the {@link AdapterView}
     * @param list The list of RemoteViews which will populate the view specified by viewId.
     */
    public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list) {
        addAction(new SetRemoteViewsAdapterList(viewId, list));
    }

    /**
     * Equivalent to calling {@link android.widget.AbsListView#smoothScrollToPosition(int, int)}.
     *
+113 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 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.
 */

package android.widget;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * @hide
 */
public class RemoteViewsListAdapter extends BaseAdapter {

    private Context mContext;
    private ArrayList<RemoteViews> mRemoteViewsList;
    private ArrayList<Integer> mViewTypes = new ArrayList<Integer>();

    public RemoteViewsListAdapter(Context context, ArrayList<RemoteViews> remoteViews) {
        mContext = context;
        mRemoteViewsList = remoteViews;
        init();
    }

    public void setViewsList(ArrayList<RemoteViews> remoteViews) {
        mRemoteViewsList = remoteViews;
        init();
        notifyDataSetChanged();
    }

    private void init() {
        if (mRemoteViewsList == null) return;

        mViewTypes.clear();
        for (RemoteViews rv: mRemoteViewsList) {
            if (!mViewTypes.contains(rv.getLayoutId())) {
                mViewTypes.add(rv.getLayoutId());
            }
        }
    }

    @Override
    public int getCount() {
        if (mRemoteViewsList != null) {
            return mRemoteViewsList.size();
        } else {
            return 0;
        }
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (position < getCount()) {
            RemoteViews rv = mRemoteViewsList.get(position);
            View v;
            if (convertView != null && rv != null &&
                    convertView.getId() == rv.getLayoutId()) {
                v = convertView;
                rv.reapply(mContext, v);
            } else {
                v = rv.apply(mContext, parent);
            }
            return v;
        } else {
            return null;
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (position < getCount()) {
            int layoutId = mRemoteViewsList.get(position).getLayoutId();
            return mViewTypes.indexOf(layoutId);
        } else {
            return 0;
        }
    }

    public int getViewTypeCount() {
        return mViewTypes.size();
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }
}