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

Commit 34dace5f authored by Adnan Begovic's avatar Adnan Begovic
Browse files

SystemUi: Support expanded styles for custom tiles.

Change-Id: Ibbbe9189c220d1172ee4bd045e810f10fad1c307
parent 552ab56f
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>

<!--
  ~ Copyright (C) 2015 The CyanogenMod 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
  -->

<!-- GridView -->
<com.android.systemui.qs.QSDetailItemsGrid
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:sysui="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="3"
        sysui:verticalSpacing="4dp"
        sysui:horizontalSpacing="4dp" />
 No newline at end of file
+149 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2015, The CyanogenMod 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 com.android.systemui.qs;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import android.widget.BaseAdapter;

import cyanogenmod.app.CustomTile;

import com.android.systemui.qs.tiles.UserDetailItemView;
import com.android.systemui.R;

/**
 * Quick settings common detail grid view with circular items.
 */
public class QSDetailItemsGrid extends PseudoGridView {
    private static final String TAG = "QSDetailItemsGrid";
    private QSDetailItemsGridAdapter mDetailItemsGridAdapter;

    public QSDetailItemsGrid(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public static QSDetailItemsGrid inflate(Context context, ViewGroup parent, boolean attach) {
        return (QSDetailItemsGrid) LayoutInflater.from(context).inflate(
                R.layout.qs_detail_items_grid, parent, attach);
    }

    public QSDetailItemsGridAdapter createAndSetAdapter(String externalPackage,
            CustomTile.ExpandedItem[] items) {
        mDetailItemsGridAdapter = new QSDetailItemsGridAdapter(externalPackage, mContext, items);
        ViewGroupAdapterBridge.link(this, mDetailItemsGridAdapter);
        return mDetailItemsGridAdapter;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setOnTouchListener(new OnTouchListener() {
            // Setting on Touch Listener for handling the touch inside ScrollView
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // Disallow the touch request for parent scroll on touch of child view
                v.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });
    }

    public static class QSDetailItemsGridAdapter extends BaseAdapter implements OnClickListener {
        private String mPkg;
        private Context mContext;
        private CustomTile.ExpandedItem[] mItems;
        private OnPseudoGriditemClickListener mOnPseudoGridItemClickListener;

        public interface OnPseudoGriditemClickListener {
            void onPsuedoGridItemClick(View view, CustomTile.ExpandedItem item);
        }

        public QSDetailItemsGridAdapter(String packageName,
                  Context context, CustomTile.ExpandedItem[] items) {
            mPkg = packageName;
            mContext = context;
            mItems = items;
        }

        public void setOnPseudoGridItemClickListener(OnPseudoGriditemClickListener
                onPseudoGridItemClickListener) {
            mOnPseudoGridItemClickListener = onPseudoGridItemClickListener;
        }

        @Override
        public int getCount() {
            return mItems.length;
        }

        @Override
        public CustomTile.ExpandedItem getItem(int position) {
            return mItems[position];
        }

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

        @Override
        public View getView(int i, View convertView, ViewGroup parent) {
            UserDetailItemView v = UserDetailItemView.convertOrInflate(
                    mContext, convertView, parent);
            CustomTile.ExpandedItem item = getItem(i);
            Drawable d = null;
            try {
                d = getPackageContext(mPkg, mContext).getResources()
                        .getDrawable(item.itemDrawableResourceId);
            } catch (Throwable t) {
                Log.w(TAG, "Error creating package context" + mPkg +
                        " id=" + item.itemDrawableResourceId, t);
            }
            if (v != convertView) {
                v.setOnClickListener(this);
            }
            String name = item.itemTitle;
            v.setActivated(true);
            v.bind(name, d);
            v.setTag(item);
            return v;
        }

        @Override
        public void onClick(View view) {
            CustomTile.ExpandedItem item = (CustomTile.ExpandedItem) view.getTag();
            mOnPseudoGridItemClickListener.onPsuedoGridItemClick(view, item);
        }
    }

    private static Context getPackageContext(String pkg, Context context) {
        Context packageContext;
        try {
            packageContext = context.createPackageContext(pkg, 0);
        } catch (Throwable t) {
            Log.w(TAG, "Error creating package context" + pkg, t);
            return null;
        }
        return packageContext;
    }
}
+61 −0
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
package com.android.systemui.qs;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -32,6 +34,8 @@ import android.widget.ListView;
import android.widget.TextView;
import com.android.systemui.R;

import cyanogenmod.app.CustomTile;

import java.util.List;

/**
@@ -93,6 +97,63 @@ public class QSDetailItemsList extends LinearLayout {
        mListView.setEmptyView(mEmpty);
    }

    public static class QSCustomDetailListAdapter extends ArrayAdapter<CustomTile.ExpandedItem> {
        private String mPackage;

        public QSCustomDetailListAdapter(String externalPackage, Context context,
                List<CustomTile.ExpandedItem> objects) {
            super(context, R.layout.qs_detail_item, objects);
            mPackage = externalPackage;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            LinearLayout view = (LinearLayout) inflater.inflate(
                    R.layout.qs_detail_item, parent, false);

            view.setClickable(false); // let list view handle this

            final CustomTile.ExpandedItem item = getItem(position);
            Drawable d = null;
            try {
                d = getPackageContext(mPackage, getContext()).getResources()
                        .getDrawable(item.itemDrawableResourceId);
            } catch (Throwable t) {
                Log.w(TAG, "Error creating package context" + mPackage +
                        " id=" + item.itemDrawableResourceId, t);
            }
            final ImageView iv = (ImageView) view.findViewById(android.R.id.icon);
            iv.setImageDrawable(d);
            iv.getOverlay().clear();
            //TODO: hide icon for the time being until the API supports granular item manipulation
            final ImageView iv2 = (ImageView) view.findViewById(android.R.id.icon2);
            iv2.setVisibility(View.GONE);
            final TextView title = (TextView) view.findViewById(android.R.id.title);
            title.setText(item.itemTitle);
            final TextView summary = (TextView) view.findViewById(android.R.id.summary);
            final boolean twoLines = !TextUtils.isEmpty(item.itemSummary);
            title.setMaxLines(twoLines ? 1 : 2);
            summary.setVisibility(twoLines ? VISIBLE : GONE);
            summary.setText(twoLines ? item.itemSummary : null);
            view.setMinimumHeight(getContext().getResources().getDimensionPixelSize(
                    twoLines ? R.dimen.qs_detail_item_height_twoline
                            : R.dimen.qs_detail_item_height));
            return view;
        }
    }

    private static Context getPackageContext(String pkg, Context context) {
        Context packageContext;
        try {
            packageContext = context.createPackageContext(pkg, 0);
        } catch (Throwable t) {
            Log.w(TAG, "Error creating package context" + pkg, t);
            return null;
        }
        return packageContext;
    }

    public static class QSDetailListAdapter extends ArrayAdapter<QSDetailItems.Item> {
        private QSDetailItems.Callback mCallback;

+82 −18
Original line number Diff line number Diff line
@@ -27,18 +27,27 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.android.internal.logging.MetricsLogger;

import com.android.systemui.qs.QSDetailItemsGrid;
import com.android.systemui.qs.QSDetailItemsList;
import cyanogenmod.app.CustomTile;
import cyanogenmod.app.StatusBarPanelCustomTile;

import com.android.systemui.R;
import com.android.systemui.qs.QSTile;

import java.util.Arrays;

public class CustomQSTile extends QSTile<QSTile.State> {

    private CustomTile.ExpandedStyle mExpandedStyle;
    private PendingIntent mOnClick;
    private Uri mOnClickUri;
    private int mCurrentUserId;
@@ -48,7 +57,6 @@ public class CustomQSTile extends QSTile<QSTile.State> {
    public CustomQSTile(Host host, StatusBarPanelCustomTile tile) {
        super(host);
        refreshState(tile);
        mDetailAdapter = new CustomQSDetailAdapter();
    }

    @Override
@@ -77,12 +85,18 @@ public class CustomQSTile extends QSTile<QSTile.State> {

    @Override
    protected void handleLongClick() {
        if (mExpandedStyle == null) {
            showDetail(true);
        }
    }

    @Override
    protected void handleClick() {
        try {
            if (mExpandedStyle != null &&
                    mExpandedStyle.getStyle() != CustomTile.ExpandedStyle.NO_STYLE) {
                showDetail(true);
            }
            if (mOnClick != null) {
                if (mOnClick.isActivity()) {
                    mHost.collapsePanels();
@@ -115,6 +129,8 @@ public class CustomQSTile extends QSTile<QSTile.State> {
        }
        mOnClick = customTile.onClick;
        mOnClickUri = customTile.onClickUri;
        mExpandedStyle = customTile.expandedStyle;
        mDetailAdapter = new CustomQSDetailAdapter();
    }

    @Override
@@ -122,9 +138,11 @@ public class CustomQSTile extends QSTile<QSTile.State> {
        return MetricsLogger.DONT_TRACK_ME_BRO;
    }

    private class CustomQSDetailAdapter implements DetailAdapter {
    private class CustomQSDetailAdapter implements DetailAdapter, AdapterView.OnItemClickListener,
            QSDetailItemsGrid.QSDetailItemsGridAdapter.OnPseudoGriditemClickListener {
        private QSDetailItemsList.QSCustomDetailListAdapter mListAdapter;
        private QSDetailItemsGrid.QSDetailItemsGridAdapter mGridAdapter;

        @Override
        public int getTitle() {
            return R.string.quick_settings_custom_tile_detail_title;
        }
@@ -157,21 +175,67 @@ public class CustomQSTile extends QSTile<QSTile.State> {

        @Override
        public View createDetailView(Context context, View convertView, ViewGroup parent) {
            LinearLayout rootView = (LinearLayout) LayoutInflater.from(context)
            View rootView = null;
            if (mExpandedStyle == null) {
                rootView = (LinearLayout) LayoutInflater.from(context)
                        .inflate(R.layout.qs_custom_detail, parent, false);
            ImageView imageView = (ImageView) rootView.findViewById(R.id.custom_qs_tile_icon);
            TextView customTileTitle = (TextView) rootView.findViewById(R.id.custom_qs_tile_title);
                ImageView imageView = (ImageView)
                        rootView.findViewById(R.id.custom_qs_tile_icon);
                TextView customTileTitle = (TextView)
                        rootView.findViewById(R.id.custom_qs_tile_title);
                TextView customTilePkg = (TextView) rootView
                        .findViewById(R.id.custom_qs_tile_package);
                TextView customTileContentDesc = (TextView) rootView
                        .findViewById(R.id.custom_qs_tile_content_description);

                // icon is cached in state, fetch it
                imageView.setImageDrawable(getState().icon.getDrawable(mContext));
                customTileTitle.setText(mTile.getCustomTile().label);
                customTilePkg.setText(mTile.getPackage());
                customTileContentDesc.setText(mTile.getCustomTile().contentDescription);
            } else {
                switch (mExpandedStyle.getStyle()) {
                    case CustomTile.ExpandedStyle.GRID_STYLE:
                        rootView = QSDetailItemsGrid.inflate(context, parent, false);
                        mGridAdapter = ((QSDetailItemsGrid) rootView)
                                .createAndSetAdapter(mTile.getPackage(),
                                        mExpandedStyle.getExpandedItems());
                        mGridAdapter.setOnPseudoGridItemClickListener(this);
                        break;
                    case CustomTile.ExpandedStyle.LIST_STYLE:
                    default:
                        rootView = QSDetailItemsList.convertOrInflate(context, convertView, parent);
                        ListView listView = ((QSDetailItemsList) rootView).getListView();
                        listView.setDivider(null);
                        listView.setOnItemClickListener(this);
                        listView.setAdapter(mListAdapter =
                                new QSDetailItemsList.QSCustomDetailListAdapter(mTile.getPackage(),
                                        context, Arrays.asList(mExpandedStyle.getExpandedItems())));
                        break;
                }
            }
            return rootView;
        }

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            CustomTile.ExpandedItem item = mListAdapter.getItem(position);
            sendEvent(item.onClickPendingIntent);
        }

        @Override
        public void onPsuedoGridItemClick(View view, CustomTile.ExpandedItem item) {
            sendEvent(item.onClickPendingIntent);
        }

        private void sendEvent(PendingIntent intent) {
            try {
                if (intent.isActivity()) {
                    mHost.collapsePanels();
                }
                intent.send();
            } catch (PendingIntent.CanceledException e) {
                //
            }
        }
    }
}
 No newline at end of file