blob: 2ef7a2a46288232276a48f1160ebac5c1c3c0f2f [file] [log] [blame]
/*
* Copyright (C) 2015 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 com.android.packageinstaller.permission.ui.wear.settings;
import android.content.Context;
import android.support.wearable.view.CircledImageView;
import android.support.wearable.view.WearableListView;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.packageinstaller.R;
import java.util.ArrayList;
/**
* Common adapter for settings views. Maintains a list of 'Settings', consisting of a name,
* icon and optional activity-specific data.
*/
public class SettingsAdapter<T> extends WearableListView.Adapter {
private static final String TAG = "SettingsAdapter";
private final Context mContext;
protected static CharSequence generateLabelWithState(
Context context, int labelId, boolean enabled) {
return generateLabelWithState(context, labelId, R.string.generic_enabled, enabled);
}
protected static CharSequence generateLabelWithState(
Context context, int labelId, int onId, boolean enabled) {
SpannableStringBuilder ssb = new SpannableStringBuilder(context.getString(labelId));
ssb.append('\n');
ssb.append(
context.getString(enabled ? onId : R.string.generic_disabled),
new TextAppearanceSpan(context, R.style.TextAppearance_Settings_Label_Large),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return ssb;
}
public static final class Setting<S> {
public static final int ID_INVALID = -1;
public final int id;
public int nameResourceId;
public CharSequence name;
public int iconResource;
public boolean inProgress;
public S data;
public Setting(CharSequence name, int iconResource, S data) {
this(name, iconResource, data, ID_INVALID);
}
public Setting(CharSequence name, int iconResource, S data, int id) {
this.name = name;
this.iconResource = iconResource;
this.data = data;
this.inProgress = false;
this.id = id;
}
public Setting(int nameResource, int iconResource, S data, int id) {
this.nameResourceId = nameResource;
this.iconResource = iconResource;
this.data = data;
this.inProgress = false;
this.id = id;
}
public Setting(int nameResource, int iconResource, int id) {
this.nameResourceId = nameResource;
this.iconResource = iconResource;
this.data = null;
this.inProgress = false;
this.id = id;
}
public Setting(CharSequence name, int iconResource, int id) {
this(name, iconResource, null, id);
}
}
private final int mItemLayoutId;
private final float mDefaultCircleRadiusPercent;
private final float mSelectedCircleRadiusPercent;
protected ArrayList<Setting<T>> mSettings = new ArrayList<Setting<T>>();
public SettingsAdapter(Context context, int itemLayoutId) {
mContext = context;
mItemLayoutId = itemLayoutId;
mDefaultCircleRadiusPercent = context.getResources().getFraction(
R.dimen.default_settings_circle_radius_percent, 1, 1);
mSelectedCircleRadiusPercent = context.getResources().getFraction(
R.dimen.selected_settings_circle_radius_percent, 1, 1);
}
@Override
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new SettingsItemHolder(new SettingsItem(parent.getContext()));
}
@Override
public void onBindViewHolder(WearableListView.ViewHolder holder, int position) {
Setting<T> setting = mSettings.get(position);
if (setting.iconResource == -1) {
((SettingsItemHolder) holder).imageView.setVisibility(View.GONE);
} else {
((SettingsItemHolder) holder).imageView.setVisibility(View.VISIBLE);
((SettingsItemHolder) holder).imageView.setImageResource(
mSettings.get(position).iconResource);
}
Log.d(TAG, "onBindViewHolder " + setting.name + " " + setting.id + " " + setting
.nameResourceId);
if (setting.name == null && setting.nameResourceId != 0) {
setting.name = mContext.getString(setting.nameResourceId);
}
((SettingsItemHolder) holder).textView.setText(setting.name);
}
@Override
public int getItemCount() {
return mSettings.size();
}
public void addSetting(CharSequence name, int iconResource) {
addSetting(name, iconResource, null);
}
public void addSetting(CharSequence name, int iconResource, T intent) {
addSetting(mSettings.size(), name, iconResource, intent);
}
public void addSetting(int index, CharSequence name, int iconResource, T intent) {
addSetting(Setting.ID_INVALID, index, name, iconResource, intent);
}
public void addSetting(int id, int index, CharSequence name, int iconResource, T intent) {
mSettings.add(index, new Setting<T>(name, iconResource, intent, id));
notifyItemInserted(index);
}
public void addSettingDontNotify(Setting<T> setting) {
mSettings.add(setting);
}
public void addSetting(Setting<T> setting) {
mSettings.add(setting);
notifyItemInserted(mSettings.size() - 1);
}
public void addSetting(int index, Setting<T> setting) {
mSettings.add(index, setting);
notifyItemInserted(index);
}
/**
* Returns the index of the setting in the adapter based on the ID supplied when it was
* originally added.
* @param id the setting's id
* @return index in the adapter of the setting. -1 if not found.
*/
public int findSetting(int id) {
for (int i = mSettings.size() - 1; i >= 0; --i) {
Setting setting = mSettings.get(i);
if (setting.id == id) {
return i;
}
}
return -1;
}
/**
* Removes a setting at the given index.
* @param index the index of the setting to be removed
*/
public void removeSetting(int index) {
mSettings.remove(index);
notifyDataSetChanged();
}
public void clearSettings() {
mSettings.clear();
notifyDataSetChanged();
}
/**
* Updates a setting in place.
* @param index the index of the setting
* @param name the updated setting name
* @param iconResource the update setting icon
* @param intent the updated intent for the setting
*/
public void updateSetting(int index, CharSequence name, int iconResource, T intent) {
Setting<T> setting = mSettings.get(index);
setting.iconResource = iconResource;
setting.name = name;
setting.data = intent;
notifyItemChanged(index);
}
public Setting<T> get(int position) {
return mSettings.get(position);
}
protected static class SettingsItemHolder extends ExtendedViewHolder {
public final CircledImageView imageView;
public final TextView textView;
public SettingsItemHolder(View itemView) {
super(itemView);
imageView = ((CircledImageView) itemView.findViewById(R.id.image));
textView = ((TextView) itemView.findViewById(R.id.text));
}
}
protected class SettingsItem extends FrameLayout implements ExtendedOnCenterProximityListener {
private final CircledImageView mImage;
private final TextView mText;
public SettingsItem(Context context) {
super(context);
View view = View.inflate(context, mItemLayoutId, null);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.CENTER_VERTICAL;
addView(view, params);
mImage = (CircledImageView) findViewById(R.id.image);
mText = (TextView) findViewById(R.id.text);
}
@Override
public float getProximityMinValue() {
return mDefaultCircleRadiusPercent;
}
@Override
public float getProximityMaxValue() {
return mSelectedCircleRadiusPercent;
}
@Override
public float getCurrentProximityValue() {
return mImage.getCircleRadiusPressedPercent();
}
@Override
public void setScalingAnimatorValue(float value) {
mImage.setCircleRadiusPercent(value);
mImage.setCircleRadiusPressedPercent(value);
}
@Override
public void onCenterPosition(boolean animate) {
mImage.setAlpha(1f);
mText.setAlpha(1f);
}
@Override
public void onNonCenterPosition(boolean animate) {
mImage.setAlpha(0.5f);
mText.setAlpha(0.5f);
}
TextView getTextView() {
return mText;
}
}
}