Remove GreenDroid
@ -1,80 +0,0 @@
|
||||
package com.todoroo.astrid.utility;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import org.tasks.R;
|
||||
import com.todoroo.andlib.service.ContextManager;
|
||||
|
||||
/**
|
||||
* This class caches common images based on resource ID to avoid
|
||||
* the performance hit from constantly loading them from disk
|
||||
* @author Sam
|
||||
*
|
||||
*/
|
||||
public class ResourceDrawableCache {
|
||||
|
||||
private static Drawable ICN_DEFAULT_PERSON_IMAGE = null;
|
||||
private static Drawable ICN_ANYONE = null;
|
||||
private static Drawable ICN_ANYONE_TRANSPARENT = null;
|
||||
private static Drawable ICN_ADD_CONTACT = null;
|
||||
|
||||
private static Drawable DEFAULT_LIST_0 = null;
|
||||
private static Drawable DEFAULT_LIST_1 = null;
|
||||
private static Drawable DEFAULT_LIST_2 = null;
|
||||
private static Drawable DEFAULT_LIST_3 = null;
|
||||
|
||||
|
||||
public static Drawable getImageDrawableFromId(Resources r, int resId) {
|
||||
if (r == null) {
|
||||
r = ContextManager.getResources();
|
||||
}
|
||||
switch(resId) {
|
||||
case R.drawable.icn_default_person_image:
|
||||
if (ICN_DEFAULT_PERSON_IMAGE == null) {
|
||||
ICN_DEFAULT_PERSON_IMAGE = r.getDrawable(resId);
|
||||
}
|
||||
return ICN_DEFAULT_PERSON_IMAGE;
|
||||
case R.drawable.icn_anyone:
|
||||
if (ICN_ANYONE == null) {
|
||||
ICN_ANYONE = r.getDrawable(resId);
|
||||
}
|
||||
return ICN_ANYONE;
|
||||
case R.drawable.icn_anyone_transparent:
|
||||
if (ICN_ANYONE_TRANSPARENT == null) {
|
||||
ICN_ANYONE_TRANSPARENT = r.getDrawable(resId);
|
||||
}
|
||||
return ICN_ANYONE_TRANSPARENT;
|
||||
case R.drawable.icn_add_contact:
|
||||
if (ICN_ADD_CONTACT == null) {
|
||||
ICN_ADD_CONTACT = r.getDrawable(resId);
|
||||
}
|
||||
return ICN_ADD_CONTACT;
|
||||
|
||||
case R.drawable.default_list_0:
|
||||
if (DEFAULT_LIST_0 == null) {
|
||||
DEFAULT_LIST_0 = r.getDrawable(resId);
|
||||
}
|
||||
return DEFAULT_LIST_0;
|
||||
case R.drawable.default_list_1:
|
||||
if (DEFAULT_LIST_1 == null) {
|
||||
DEFAULT_LIST_1 = r.getDrawable(resId);
|
||||
}
|
||||
return DEFAULT_LIST_1;
|
||||
case R.drawable.default_list_2:
|
||||
if (DEFAULT_LIST_2 == null) {
|
||||
DEFAULT_LIST_2 = r.getDrawable(resId);
|
||||
}
|
||||
return DEFAULT_LIST_2;
|
||||
case R.drawable.default_list_3:
|
||||
if (DEFAULT_LIST_3 == null) {
|
||||
DEFAULT_LIST_3 = r.getDrawable(resId);
|
||||
}
|
||||
return DEFAULT_LIST_3;
|
||||
|
||||
default:
|
||||
return r.getDrawable(resId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 508 B |
|
Before Width: | Height: | Size: 678 B |
|
Before Width: | Height: | Size: 571 B |
|
Before Width: | Height: | Size: 1.8 KiB |
@ -1,77 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
** Copyright (c) 2012 Todoroo Inc
|
||||
**
|
||||
** See the file "LICENSE" for the full license governing this code.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:astrid="http://schemas.android.com/apk/res/org.tasks"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="55dip"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:drawable/list_selector_background"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingBottom="5dip"
|
||||
android:paddingLeft="6dip"
|
||||
android:paddingRight="6dip">
|
||||
|
||||
<!-- title -->
|
||||
<TextView android:id="@+id/title"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:paddingLeft="5dip"
|
||||
android:paddingRight="3dip"
|
||||
style="@style/TextAppearance.TAd_ItemTitle"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
|
||||
<!-- activity date -->
|
||||
<TextView android:id="@+id/date"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_alignLeft="@id/title"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:paddingTop="1dip"
|
||||
style="@style/TextAppearance.TAd_ItemDueDate"
|
||||
android:textStyle="normal"
|
||||
android:gravity="left"
|
||||
android:ellipsize="end"
|
||||
android:textSize="12sp"
|
||||
android:singleLine="true"/>
|
||||
|
||||
|
||||
<!-- picture -->
|
||||
<com.todoroo.astrid.helper.AsyncImageView android:id="@+id/comment_picture"
|
||||
android:layout_width="100dip"
|
||||
android:layout_height="100dip"
|
||||
android:layout_below="@id/date"
|
||||
android:paddingTop="5dip"
|
||||
astrid:defaultSrc="@drawable/icn_default_person_image"
|
||||
android:scaleType="fitStart"
|
||||
android:layout_marginLeft="50dip"
|
||||
android:visibility="gone" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- picture -->
|
||||
<com.todoroo.astrid.helper.AsyncImageView
|
||||
android:id="@+id/comment_picture"
|
||||
android:layout_width="50dip"
|
||||
android:layout_height="50dip"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginBottom="4dip"
|
||||
android:visibility="gone"
|
||||
astrid:defaultSrc="@android:drawable/ic_menu_gallery"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
</LinearLayout>
|
||||
@ -1,29 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:0.5.+'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'android-library'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 18
|
||||
buildToolsVersion "18.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 7
|
||||
targetSdkVersion 18
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-v4:18.0.0'
|
||||
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
android.library=true
|
||||
# Indicates whether an apk should be generated for each density.
|
||||
split.density=false
|
||||
# Project target.
|
||||
target=android-18
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.cyrilmottier.android.greendroid"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<application/>
|
||||
</manifest>
|
||||
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.app;
|
||||
|
||||
import greendroid.widget.GDActionBar;
|
||||
import greendroid.widget.ActionBarItem;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* Defines all methods related to Activities embedding an {@link GDActionBar}
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public interface ActionBarActivity {
|
||||
|
||||
/**
|
||||
* The optional title of the launched ActionBarActivity
|
||||
*
|
||||
* @see Activity#setTitle(CharSequence)
|
||||
* @see Activity#setTitle(int)
|
||||
*/
|
||||
static final String GD_ACTION_BAR_TITLE = "greendroid.app.ActionBarActivity.GD_ACTION_BAR_TITLE";
|
||||
|
||||
/**
|
||||
* An integer that can be used to force the ActionBar to a particular
|
||||
* visibility. This is especially useful when using GDActivity inside a
|
||||
* GDTabActivity.
|
||||
*
|
||||
* @see View#VISIBLE
|
||||
* @see View#INVISIBLE
|
||||
* @see View#GONE
|
||||
*/
|
||||
static final String GD_ACTION_BAR_VISIBILITY = "greendroid.app.ActionBarActivity.GD_ACTION_BAR_VISIBILITY";
|
||||
|
||||
/**
|
||||
* Clients may use this method to listen to {@link ActionBarItem}s clicks.
|
||||
*
|
||||
* @param item The {@link ActionBarItem} that has been clicked
|
||||
* @param position The position of the clicked item. This number is equal or
|
||||
* greater to zero. 0 is the leftmost item.
|
||||
* @return true if the method has handled the click on the
|
||||
* {@link ActionBarItem} at position <em>position</em>. Otherwise it
|
||||
* returns false.
|
||||
*/
|
||||
boolean onHandleActionBarItemClick(ActionBarItem item, int position);
|
||||
|
||||
/**
|
||||
* Returns the content view. Please note the content view is not the entire
|
||||
* view but a {@link FrameLayout} that contains everything but the
|
||||
* {@link GDActionBar}.
|
||||
*
|
||||
* @return The content view
|
||||
*/
|
||||
FrameLayout getContentView();
|
||||
|
||||
/**
|
||||
* Returns the {@link GDActionBar}. Listening to {@link GDActionBar} events
|
||||
* should be done via the
|
||||
* {@link ActionBarActivity#onHandleActionBarItemClick(ActionBarItem, int)}
|
||||
* method. Most of the time, this method don't need to be used directly.
|
||||
*
|
||||
* @see {@link ActionBarActivity#onHandleActionBarItemClick(ActionBarItem, int)}
|
||||
* @see {@link ActionBarActivity#addActionBarItem(ActionBarItem)}
|
||||
* @see {@link ActionBarActivity#addActionBarItem(greendroid.widget.ActionBarItem.Type)}
|
||||
* @return The {@link GDActionBar} currently displayed on screen
|
||||
*/
|
||||
GDActionBar getGDActionBar();
|
||||
|
||||
/**
|
||||
* A simple utility method that casts the {@link Application} returned by
|
||||
* {@link #getApplication()} into a {@link GDApplication}
|
||||
*
|
||||
* @return The current {@link GDApplication}
|
||||
*/
|
||||
GDApplication getGDApplication();
|
||||
|
||||
/**
|
||||
* Add a new item to the {@link GDActionBar}.
|
||||
*
|
||||
* @param item The item to add to the {@link GDActionBar}
|
||||
*/
|
||||
ActionBarItem addActionBarItem(ActionBarItem item);
|
||||
|
||||
/**
|
||||
* Add a new item to the {@link GDActionBar}.
|
||||
*
|
||||
* @param item The item to add to the {@link GDActionBar}
|
||||
* @param itemId Unique item ID. Use {@link GDActionBar#NONE} if you do not
|
||||
* need a unique ID.
|
||||
*/
|
||||
ActionBarItem addActionBarItem(ActionBarItem item, int itemId);
|
||||
|
||||
/**
|
||||
* Adds a new item of type <em>type</em> to the {@link GDActionBar}.
|
||||
*
|
||||
* @param actionBarItemType The item to add to the {@link GDActionBar}
|
||||
*/
|
||||
ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType);
|
||||
|
||||
/**
|
||||
* Adds a new item of type <em>type</em> to the {@link GDActionBar}.
|
||||
*
|
||||
* @param actionBarItemType The item to add to the {@link GDActionBar}
|
||||
* @param itemId Unique item ID. Use {@link GDActionBar#NONE} if you do not
|
||||
* need a unique ID.
|
||||
*/
|
||||
ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType, int itemId);
|
||||
|
||||
/**
|
||||
* Returns the identifier of the layout that needs to be created for this
|
||||
* {@link ActionBarActivity}
|
||||
*
|
||||
* @return The layout identifier of the layout to create
|
||||
*/
|
||||
int createLayout();
|
||||
|
||||
/**
|
||||
* Called at the beginning of the {@link Activity#onContentChanged()}
|
||||
* method. This may be used to initialize all references on elements.
|
||||
*/
|
||||
void onPreContentChanged();
|
||||
|
||||
/**
|
||||
* Called at the end of the {@link Activity#onContentChanged()} method. This
|
||||
* may be use to initialize the content of the layout (titles, etc.)
|
||||
*/
|
||||
void onPostContentChanged();
|
||||
}
|
||||
@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.app;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
import greendroid.util.Config;
|
||||
import greendroid.widget.GDActionBar;
|
||||
import greendroid.widget.ActionBarHost;
|
||||
import greendroid.widget.ActionBarItem;
|
||||
import greendroid.widget.GDActionBar.OnActionBarListener;
|
||||
import greendroid.widget.GDActionBar.Type;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An {@link GDActivity} is a regular Activity that always hosts an
|
||||
* {@link GDActionBar}. It is extremely simple to use as you have nothing
|
||||
* particular to do. Indeed, the ActionBar is automatically added to your own
|
||||
* layout when using the {@link #getContentView()} method. You can also use one
|
||||
* of the setActionBarContentView utility methods. As a result, a basic
|
||||
* {@link GDActivity} will often be initialized using the following snippet of
|
||||
* code:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* protected void onCreate(Bundle savedInstanceState) {
|
||||
* super.onCreate(savedInstanceState);
|
||||
*
|
||||
* setActionBarContentView(R.layout.main);
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* An ActionBar is a widget that may contains actions items and a title. You can
|
||||
* also set the title putting an extra string with the key
|
||||
* {@link GD_ACTION_BAR_TITLE} in your Intent:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* Intent intent = new Intent(this, MyGDActivity.class);
|
||||
* intent.putExtra(ActionBarActivity.GD_ACTION_BAR_TITLE, "Next screen title");
|
||||
* startActivity(intent);
|
||||
* </pre>
|
||||
* <p>
|
||||
* Note: An {@link GDActivity} automatically handle the type of the ActionBar
|
||||
* (Dashboard or Normal) depending on the value returned by the
|
||||
* getHomeActivityClass of your {@link GDApplication}. However you can force the
|
||||
* type of the action bar in your constructor.
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* public MyGDActivity() {
|
||||
* super(ActionBar.Type.Dashboard);
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* All Activities that inherits from an {@link GDActivity} are notified when an
|
||||
* action button is tapped in the onHandleActionBarItemClick(ActionBarItem, int)
|
||||
* method. By default this method does nothing but return false.
|
||||
* </p>
|
||||
*
|
||||
* @see {@link GDApplication#getHomeActivityClass()}
|
||||
* @see {@link ActionBarActivity#GD_ACTION_BAR_TITLE}
|
||||
* @see {@link GDActivity#setActionBarContentView(int)}
|
||||
* @see {@link GDActivity#setActionBarContentView(View)}
|
||||
* @see {@link GDActivity#setActionBarContentView(View, LayoutParams)}
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class GDActivity extends Activity implements ActionBarActivity {
|
||||
|
||||
private static final String LOG_TAG = GDActivity.class.getSimpleName();
|
||||
|
||||
private boolean mDefaultConstructorUsed = false;
|
||||
|
||||
private Type mActionBarType;
|
||||
private ActionBarHost mActionBarHost;
|
||||
|
||||
public GDActivity() {
|
||||
this(Type.Normal);
|
||||
mDefaultConstructorUsed = true;
|
||||
}
|
||||
|
||||
public GDActivity(GDActionBar.Type actionBarType) {
|
||||
super();
|
||||
mActionBarType = actionBarType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
ensureLayout();
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (mDefaultConstructorUsed) {
|
||||
// HACK cyril: This should have been done is the default
|
||||
// constructor. Unfortunately, the getApplication() method returns
|
||||
// null there. Hence, this has to be done here.
|
||||
if (getClass().equals(getGDApplication().getHomeActivityClass())) {
|
||||
mActionBarType = Type.Dashboard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
ensureLayout();
|
||||
}
|
||||
|
||||
public GDActionBar.Type getActionBarType() {
|
||||
return mActionBarType;
|
||||
}
|
||||
|
||||
public int createLayout() {
|
||||
switch (mActionBarType) {
|
||||
case Dashboard:
|
||||
return R.layout.gd_content_dashboard;
|
||||
case Empty:
|
||||
return R.layout.gd_content_empty;
|
||||
case Normal:
|
||||
default:
|
||||
return R.layout.gd_content_normal;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureLayout() {
|
||||
if (!verifyLayout()) {
|
||||
setContentView(createLayout());
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean verifyLayout() {
|
||||
return mActionBarHost != null;
|
||||
}
|
||||
|
||||
public GDApplication getGDApplication() {
|
||||
return (GDApplication) getApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
|
||||
onPreContentChanged();
|
||||
onPostContentChanged();
|
||||
}
|
||||
|
||||
public void onPreContentChanged() {
|
||||
mActionBarHost = (ActionBarHost) findViewById(R.id.gd_action_bar_host);
|
||||
if (mActionBarHost == null) {
|
||||
throw new RuntimeException(
|
||||
"Your content must have an ActionBarHost whose id attribute is R.id.gd_action_bar_host");
|
||||
}
|
||||
mActionBarHost.getActionBar().setOnActionBarListener(mActionBarListener);
|
||||
}
|
||||
|
||||
public void onPostContentChanged() {
|
||||
|
||||
boolean titleSet = false;
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
String title = intent.getStringExtra(ActionBarActivity.GD_ACTION_BAR_TITLE);
|
||||
if (title != null) {
|
||||
titleSet = true;
|
||||
setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
if (!titleSet) {
|
||||
// No title has been set via the Intent. Let's look in the
|
||||
// ActivityInfo
|
||||
try {
|
||||
final ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), 0);
|
||||
if (activityInfo.labelRes != 0) {
|
||||
setTitle(activityInfo.labelRes);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
final int visibility = intent.getIntExtra(ActionBarActivity.GD_ACTION_BAR_VISIBILITY, View.VISIBLE);
|
||||
getGDActionBar().setVisibility(visibility);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
getGDActionBar().setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(int titleId) {
|
||||
setTitle(getString(titleId));
|
||||
}
|
||||
|
||||
public GDActionBar getGDActionBar() {
|
||||
ensureLayout();
|
||||
return mActionBarHost.getActionBar();
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem item) {
|
||||
return getGDActionBar().addItem(item);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem item, int itemId) {
|
||||
return getGDActionBar().addItem(item, itemId);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType) {
|
||||
return getGDActionBar().addItem(actionBarItemType);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType, int itemId) {
|
||||
return getGDActionBar().addItem(actionBarItemType, itemId);
|
||||
}
|
||||
|
||||
public FrameLayout getContentView() {
|
||||
ensureLayout();
|
||||
return mActionBarHost.getContentView();
|
||||
}
|
||||
|
||||
public void setActionBarContentView(int resID) {
|
||||
LayoutInflater.from(this).inflate(resID, getContentView());
|
||||
}
|
||||
|
||||
public void setActionBarContentView(View view, LayoutParams params) {
|
||||
getContentView().addView(view, params);
|
||||
}
|
||||
|
||||
public void setActionBarContentView(View view) {
|
||||
getContentView().addView(view);
|
||||
}
|
||||
|
||||
public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private OnActionBarListener mActionBarListener = new OnActionBarListener() {
|
||||
public void onActionBarItemClicked(int position) {
|
||||
if (position == OnActionBarListener.HOME_ITEM) {
|
||||
|
||||
final GDApplication app = getGDApplication();
|
||||
switch (mActionBarType) {
|
||||
case Normal:
|
||||
final Class<?> klass = app.getHomeActivityClass();
|
||||
if (klass != null && !klass.equals(GDActivity.this.getClass())) {
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.i(LOG_TAG, "Going back to the home activity");
|
||||
}
|
||||
Intent homeIntent = new Intent(GDActivity.this, klass);
|
||||
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(homeIntent);
|
||||
}
|
||||
break;
|
||||
case Dashboard:
|
||||
final Intent appIntent = app.getMainApplicationIntent();
|
||||
if (appIntent != null) {
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.i(LOG_TAG, "Launching the main application Intent");
|
||||
}
|
||||
startActivity(appIntent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!onHandleActionBarItemClick(getGDActionBar().getItem(position), position)) {
|
||||
if (Config.GD_WARNING_LOGS_ENABLED) {
|
||||
Log.w(LOG_TAG, "Click on item at position " + position + " dropped down to the floor");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.app;
|
||||
|
||||
import greendroid.image.ImageCache;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Defines various methods that should be overridden in order to style your
|
||||
* application.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class GDApplication extends Application {
|
||||
|
||||
/**
|
||||
* Used for receiving low memory system notification. You should definitely
|
||||
* use it in order to clear caches and not important data everytime the
|
||||
* system need memory.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
* @see GDApplication#registerOnLowMemoryListener(OnLowMemoryListener)
|
||||
* @see GDApplication#unregisterOnLowMemoryListener(OnLowMemoryListener)
|
||||
*/
|
||||
public static interface OnLowMemoryListener {
|
||||
public void onLowMemoryReceived();
|
||||
}
|
||||
|
||||
private static final int CORE_POOL_SIZE = 5;
|
||||
|
||||
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
|
||||
private final AtomicInteger mCount = new AtomicInteger(1);
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
return new Thread(r, "GreenDroid thread #" + mCount.getAndIncrement());
|
||||
}
|
||||
};
|
||||
|
||||
private ExecutorService mExecutorService;
|
||||
private ImageCache mImageCache;
|
||||
private ArrayList<WeakReference<OnLowMemoryListener>> mLowMemoryListeners;
|
||||
|
||||
public GDApplication() {
|
||||
mLowMemoryListeners = new ArrayList<WeakReference<OnLowMemoryListener>>();
|
||||
}
|
||||
|
||||
public ExecutorService getExecutor() {
|
||||
if (mExecutorService == null) {
|
||||
mExecutorService = Executors.newFixedThreadPool(CORE_POOL_SIZE, sThreadFactory);
|
||||
}
|
||||
return mExecutorService;
|
||||
}
|
||||
|
||||
public ImageCache getImageCache() {
|
||||
if (mImageCache == null) {
|
||||
mImageCache = new ImageCache(this);
|
||||
}
|
||||
return mImageCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class of the home {@link Activity}. The home {@link Activity}
|
||||
* is the main entrance point of your application. This is usually where the
|
||||
* dashboard/general menu is displayed.
|
||||
*
|
||||
* @return The Class of the home {@link Activity}
|
||||
*/
|
||||
public Class<?> getHomeActivityClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each application may have an "application intent" which will be used when
|
||||
* the user clicked on the application button.
|
||||
*
|
||||
* @return The main application {@link Intent} (may be null if you don't
|
||||
* want to use the main application {@link Intent} feature)
|
||||
*/
|
||||
public Intent getMainApplicationIntent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new listener to the list
|
||||
*
|
||||
* @param listener The listener to unregister
|
||||
* @see {@link OnLowMemoryListener}
|
||||
*/
|
||||
public void registerOnLowMemoryListener(OnLowMemoryListener listener) {
|
||||
if (listener != null) {
|
||||
mLowMemoryListeners.add(new WeakReference<OnLowMemoryListener>(listener));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a previously registered listener
|
||||
*
|
||||
* @param listener The listener to unregister
|
||||
* @see {@link OnLowMemoryListener}
|
||||
*/
|
||||
public void unregisterOnLowMemoryListener(OnLowMemoryListener listener) {
|
||||
if (listener != null) {
|
||||
int i = 0;
|
||||
while (i < mLowMemoryListeners.size()) {
|
||||
final OnLowMemoryListener l = mLowMemoryListeners.get(i).get();
|
||||
if (l == null || l == listener) {
|
||||
mLowMemoryListeners.remove(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
int i = 0;
|
||||
while (i < mLowMemoryListeners.size()) {
|
||||
final OnLowMemoryListener listener = mLowMemoryListeners.get(i).get();
|
||||
if (listener == null) {
|
||||
mLowMemoryListeners.remove(i);
|
||||
} else {
|
||||
listener.onLowMemoryReceived();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.app;
|
||||
|
||||
import greendroid.util.Config;
|
||||
import greendroid.widget.GDActionBar;
|
||||
import android.app.ListActivity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* An equivalent to {@link ListActivity} that manages a ListView.
|
||||
*
|
||||
* @see {@link ListActivity}
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class GDListActivity extends GDActivity {
|
||||
|
||||
private static final String LOG_TAG = GDListActivity.class.getSimpleName();
|
||||
|
||||
private ListAdapter mAdapter;
|
||||
private ListView mList;
|
||||
private View mEmptyView;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private boolean mFinishedStart = false;
|
||||
|
||||
private Runnable mRequestFocus = new Runnable() {
|
||||
public void run() {
|
||||
mList.focusableViewAvailable(mList);
|
||||
}
|
||||
};
|
||||
|
||||
public GDListActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
public GDListActivity(GDActionBar.Type actionBarType) {
|
||||
super(actionBarType);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called when an item in the list is selected.
|
||||
* Subclasses should override. Subclasses can call
|
||||
* getListView().getItemAtPosition(position) if they need to access the data
|
||||
* associated with the selected item.
|
||||
*
|
||||
* @param l The ListView where the click happened
|
||||
* @param v The view that was clicked within the ListView
|
||||
* @param position The position of the view in the list
|
||||
* @param id The row id of the item that was clicked
|
||||
*/
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the cursor for the list view.
|
||||
*/
|
||||
public void setListAdapter(ListAdapter adapter) {
|
||||
synchronized (this) {
|
||||
ensureLayout();
|
||||
mAdapter = adapter;
|
||||
mList.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the currently selected list item to the specified position with the
|
||||
* adapter's data
|
||||
*
|
||||
* @param position
|
||||
*/
|
||||
public void setSelection(int position) {
|
||||
mList.setSelection(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the currently selected list item.
|
||||
*/
|
||||
public int getSelectedItemPosition() {
|
||||
return mList.getSelectedItemPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cursor row ID of the currently selected list item.
|
||||
*/
|
||||
public long getSelectedItemId() {
|
||||
return mList.getSelectedItemId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activity's list view widget.
|
||||
*/
|
||||
public ListView getListView() {
|
||||
ensureLayout();
|
||||
return mList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ListAdapter associated with this activity's ListView.
|
||||
*/
|
||||
public ListAdapter getListAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int createLayout() {
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.d(LOG_TAG, "No layout specified : creating the default layout");
|
||||
}
|
||||
|
||||
switch (getActionBarType()) {
|
||||
case Dashboard:
|
||||
return R.layout.gd_list_content_dashboard;
|
||||
case Empty:
|
||||
return R.layout.gd_list_content_empty;
|
||||
case Normal:
|
||||
default:
|
||||
return R.layout.gd_list_content_normal;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyLayout() {
|
||||
return super.verifyLayout() && mList != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreContentChanged() {
|
||||
super.onPreContentChanged();
|
||||
|
||||
mEmptyView = findViewById(android.R.id.empty);
|
||||
mList = (ListView) findViewById(android.R.id.list);
|
||||
if (mList == null) {
|
||||
throw new RuntimeException("Your content must have a ListView whose id attribute is "
|
||||
+ "'android.R.id.list'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostContentChanged() {
|
||||
super.onPostContentChanged();
|
||||
|
||||
if (mEmptyView != null) {
|
||||
mList.setEmptyView(mEmptyView);
|
||||
}
|
||||
mList.setOnItemClickListener(mOnClickListener);
|
||||
if (mFinishedStart) {
|
||||
setListAdapter(mAdapter);
|
||||
}
|
||||
mHandler.post(mRequestFocus);
|
||||
mFinishedStart = true;
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
|
||||
onListItemClick((ListView) parent, v, position, id);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.app;
|
||||
|
||||
import greendroid.util.Config;
|
||||
import greendroid.widget.GDActionBar;
|
||||
import greendroid.widget.GDActionBar.OnActionBarListener;
|
||||
import greendroid.widget.ActionBarHost;
|
||||
import greendroid.widget.ActionBarItem;
|
||||
import android.app.TabActivity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TabHost;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* An equivalent to a TabActivity that manages fancy tabs and an ActionBar
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class GDTabActivity extends TabActivity implements ActionBarActivity {
|
||||
|
||||
private static final String LOG_TAG = GDTabActivity.class.getSimpleName();
|
||||
|
||||
private ActionBarHost mActionBarHost;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(createLayout());
|
||||
}
|
||||
|
||||
public int createLayout() {
|
||||
return R.layout.gd_tab_content;
|
||||
}
|
||||
|
||||
public GDApplication getGDApplication() {
|
||||
return (GDApplication) getApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
|
||||
onPreContentChanged();
|
||||
onPostContentChanged();
|
||||
}
|
||||
|
||||
public void onPreContentChanged() {
|
||||
mActionBarHost = (ActionBarHost) findViewById(R.id.gd_action_bar_host);
|
||||
if (mActionBarHost == null) {
|
||||
throw new RuntimeException(
|
||||
"Your content must have an ActionBarHost whose id attribute is R.id.gd_action_bar_host");
|
||||
}
|
||||
mActionBarHost.getActionBar().setOnActionBarListener(mActionBarListener);
|
||||
}
|
||||
|
||||
public void onPostContentChanged() {
|
||||
|
||||
boolean titleSet = false;
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
String title = intent.getStringExtra(ActionBarActivity.GD_ACTION_BAR_TITLE);
|
||||
if (title != null) {
|
||||
titleSet = true;
|
||||
setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
if (!titleSet) {
|
||||
// No title has been set via the Intent. Let's look in the
|
||||
// ActivityInfo
|
||||
try {
|
||||
final ActivityInfo activityInfo = getPackageManager().getActivityInfo(getComponentName(), 0);
|
||||
if (activityInfo.labelRes != 0) {
|
||||
setTitle(activityInfo.labelRes);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
final int visibility = intent.getIntExtra(ActionBarActivity.GD_ACTION_BAR_VISIBILITY, View.VISIBLE);
|
||||
getGDActionBar().setVisibility(visibility);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected void onTitleChanged(CharSequence title, int color) {
|
||||
// setTitle(title);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
getGDActionBar().setTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(int titleId) {
|
||||
setTitle(getString(titleId));
|
||||
}
|
||||
|
||||
public GDActionBar getGDActionBar() {
|
||||
return mActionBarHost.getActionBar();
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem item) {
|
||||
return getGDActionBar().addItem(item);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem item, int itemId) {
|
||||
return getGDActionBar().addItem(item, itemId);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType) {
|
||||
return getGDActionBar().addItem(actionBarItemType);
|
||||
}
|
||||
|
||||
public ActionBarItem addActionBarItem(ActionBarItem.Type actionBarItemType, int itemId) {
|
||||
return getGDActionBar().addItem(actionBarItemType, itemId);
|
||||
}
|
||||
|
||||
public FrameLayout getContentView() {
|
||||
return mActionBarHost.getContentView();
|
||||
}
|
||||
|
||||
public boolean onHandleActionBarItemClick(ActionBarItem item, int position) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private OnActionBarListener mActionBarListener = new OnActionBarListener() {
|
||||
public void onActionBarItemClicked(int position) {
|
||||
if (position == OnActionBarListener.HOME_ITEM) {
|
||||
|
||||
final Class<?> klass = getGDApplication().getHomeActivityClass();
|
||||
if (klass != null && !klass.equals(GDTabActivity.class.getClass())) {
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.i(LOG_TAG, "Going back to the home activity");
|
||||
}
|
||||
Intent homeIntent = new Intent(GDTabActivity.this, klass);
|
||||
homeIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(homeIntent);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!onHandleActionBarItemClick(getGDActionBar().getItem(position), position)) {
|
||||
if (Config.GD_WARNING_LOGS_ENABLED) {
|
||||
Log.w(LOG_TAG, "Click on item at position " + position + " dropped down to the floor");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* GDTabActivity methods
|
||||
*/
|
||||
|
||||
public void addTab(String tag, int labelId, Intent intent) {
|
||||
addTab(tag, getString(labelId), intent);
|
||||
}
|
||||
|
||||
public void addTab(String tag, CharSequence label, Intent intent) {
|
||||
final TabHost host = getTabHost();
|
||||
|
||||
View indicator = createTabIndicator(label);
|
||||
if (indicator == null) {
|
||||
final TextView textIndicator = (TextView) getLayoutInflater().inflate(R.layout.gd_tab_indicator,
|
||||
getTabWidget(), false);
|
||||
textIndicator.setText(label);
|
||||
indicator = textIndicator;
|
||||
}
|
||||
|
||||
host.addTab(host.newTabSpec(tag).setIndicator(indicator).setContent(intent));
|
||||
}
|
||||
|
||||
protected View createTabIndicator(CharSequence label) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.graphics.drawable;
|
||||
|
||||
import greendroid.widget.GDActionBar;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.LightingColorFilter;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.StateSet;
|
||||
|
||||
/**
|
||||
* A specialized {@link Drawable} that is dedicated to {@link ActionBarItem}s.
|
||||
* It automatically adapts its color depending on its current state (black when
|
||||
* pressed or focused and white otherwise). As a result, the
|
||||
* {@link AutoColorDrawable} is a replacement {@link StateListDrawable} that
|
||||
* should be used in {@link GDActionBar}s.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ActionBarDrawable extends BitmapDrawable {
|
||||
|
||||
private ColorFilter mNormalCf;
|
||||
private ColorFilter mAltCf;
|
||||
|
||||
public ActionBarDrawable(Resources res, int resId) {
|
||||
this(res, res.getDrawable(resId), Color.WHITE, Color.BLACK);
|
||||
}
|
||||
|
||||
public ActionBarDrawable(Resources res, Drawable d) {
|
||||
this(res, d, Color.WHITE, Color.BLACK);
|
||||
}
|
||||
|
||||
public ActionBarDrawable(Resources res, int resId, int normalColor, int altColor) {
|
||||
this(res, res.getDrawable(resId), normalColor, altColor);
|
||||
}
|
||||
|
||||
public ActionBarDrawable(Resources res, Drawable d, int normalColor, int altColor) {
|
||||
super(res, (d instanceof BitmapDrawable) ? ((BitmapDrawable) d).getBitmap() : null);
|
||||
mNormalCf = new LightingColorFilter(Color.BLACK, normalColor);
|
||||
mAltCf = new LightingColorFilter(Color.BLACK, altColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] stateSet) {
|
||||
final boolean useAlt = StateSet.stateSetMatches(DrawableStateSet.ENABLED_PRESSED_STATE_SET, stateSet)
|
||||
|| StateSet.stateSetMatches(DrawableStateSet.ENABLED_FOCUSED_STATE_SET, stateSet);
|
||||
setColorFilter(useAlt ? mAltCf : mNormalCf);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.graphics.drawable;
|
||||
|
||||
public class DrawableStateSet {
|
||||
|
||||
public static final int[] EMPTY_STATE_SET = {};
|
||||
|
||||
public static final int[] ENABLED_PRESSED_STATE_SET = {
|
||||
android.R.attr.state_enabled, android.R.attr.state_pressed
|
||||
};
|
||||
|
||||
public static final int[] ENABLED_FOCUSED_STATE_SET = {
|
||||
android.R.attr.state_enabled, android.R.attr.state_focused
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.image;
|
||||
|
||||
import greendroid.app.GDApplication.OnLowMemoryListener;
|
||||
import greendroid.util.GDUtils;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public class ImageCache implements OnLowMemoryListener {
|
||||
|
||||
private final HashMap<String, SoftReference<Bitmap>> mSoftCache;
|
||||
|
||||
public ImageCache(Context context) {
|
||||
mSoftCache = new HashMap<String, SoftReference<Bitmap>>();
|
||||
GDUtils.getGDApplication(context).registerOnLowMemoryListener(this);
|
||||
}
|
||||
|
||||
public static ImageCache from(Context context) {
|
||||
return GDUtils.getImageCache(context);
|
||||
}
|
||||
|
||||
public Bitmap get(String url) {
|
||||
final SoftReference<Bitmap> ref = mSoftCache.get(url);
|
||||
if (ref == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Bitmap bitmap = ref.get();
|
||||
if (bitmap == null) {
|
||||
mSoftCache.remove(url);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void put(String url, Bitmap bitmap) {
|
||||
mSoftCache.put(url, new SoftReference<Bitmap>(bitmap));
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
mSoftCache.clear();
|
||||
}
|
||||
|
||||
public void onLowMemoryReceived() {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.image;
|
||||
|
||||
import greendroid.util.Config;
|
||||
import greendroid.util.GDUtils;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* An ImageLoader asynchronously loads image from a given url. Client may be
|
||||
* notified from the current image loading state using the
|
||||
* {@link ImageLoaderCallback}.
|
||||
* <p>
|
||||
* <em><strong>Note: </strong>You normally don't need to use the {@link ImageLoader}
|
||||
* class directly in your application. You'll generally prefer using an
|
||||
* {@link ImageRequest} that takes care of the entire loading process.</em>
|
||||
* </p>
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ImageLoader {
|
||||
|
||||
private static final String LOG_TAG = ImageLoader.class.getSimpleName();
|
||||
|
||||
public static interface ImageLoaderCallback {
|
||||
|
||||
void onImageLoadingStarted(ImageLoader loader);
|
||||
|
||||
void onImageLoadingEnded(ImageLoader loader, Bitmap bitmap);
|
||||
|
||||
void onImageLoadingFailed(ImageLoader loader, Throwable exception);
|
||||
}
|
||||
|
||||
private static final int ON_START = 0x100;
|
||||
private static final int ON_FAIL = 0x101;
|
||||
private static final int ON_END = 0x102;
|
||||
|
||||
private static ImageCache sImageCache;
|
||||
private static ExecutorService sExecutor;
|
||||
private static BitmapFactory.Options sDefaultOptions;
|
||||
|
||||
public ImageLoader(Context context) {
|
||||
if (sImageCache == null) {
|
||||
sImageCache = GDUtils.getImageCache(context);
|
||||
}
|
||||
if (sExecutor == null) {
|
||||
sExecutor = GDUtils.getExecutor(context);
|
||||
}
|
||||
if (sDefaultOptions == null) {
|
||||
sDefaultOptions = new BitmapFactory.Options();
|
||||
sDefaultOptions.inDither = true;
|
||||
sDefaultOptions.inScaled = true;
|
||||
sDefaultOptions.inDensity = DisplayMetrics.DENSITY_MEDIUM;
|
||||
sDefaultOptions.inTargetDensity = context.getResources().getDisplayMetrics().densityDpi;
|
||||
}
|
||||
}
|
||||
|
||||
public Future<?> loadImage(String url, ImageLoaderCallback callback) {
|
||||
return loadImage(url, callback, null);
|
||||
}
|
||||
|
||||
public Future<?> loadImage(String url, ImageLoaderCallback callback, ImageProcessor bitmapProcessor) {
|
||||
return loadImage(url, callback, bitmapProcessor, null);
|
||||
}
|
||||
|
||||
public Future<?> loadImage(String url, ImageLoaderCallback callback, ImageProcessor bitmapProcessor, BitmapFactory.Options options) {
|
||||
return sExecutor.submit(new ImageFetcher(url, callback, bitmapProcessor, options));
|
||||
}
|
||||
|
||||
private class ImageFetcher implements Runnable {
|
||||
|
||||
private String mUrl;
|
||||
private ImageHandler mHandler;
|
||||
private ImageProcessor mBitmapProcessor;
|
||||
private BitmapFactory.Options mOptions;
|
||||
|
||||
public ImageFetcher(String url, ImageLoaderCallback callback, ImageProcessor bitmapProcessor, BitmapFactory.Options options) {
|
||||
mUrl = url;
|
||||
mHandler = new ImageHandler(url, callback);
|
||||
mBitmapProcessor = bitmapProcessor;
|
||||
mOptions = options;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
|
||||
final Handler h = mHandler;
|
||||
Bitmap bitmap = null;
|
||||
Throwable throwable = null;
|
||||
|
||||
h.sendMessage(Message.obtain(h, ON_START));
|
||||
|
||||
try {
|
||||
|
||||
if (TextUtils.isEmpty(mUrl)) {
|
||||
throw new Exception("The given URL cannot be null or empty");
|
||||
}
|
||||
|
||||
// TODO Cyril: Use a AndroidHttpClient?
|
||||
bitmap = BitmapFactory.decodeStream(new URL(mUrl).openStream(), null, (mOptions == null) ? sDefaultOptions : mOptions);
|
||||
|
||||
if (mBitmapProcessor != null && bitmap != null) {
|
||||
final Bitmap processedBitmap = mBitmapProcessor.processImage(bitmap);
|
||||
if (processedBitmap != null) {
|
||||
bitmap = processedBitmap;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// An error occured while retrieving the image
|
||||
if (Config.GD_ERROR_LOGS_ENABLED) {
|
||||
Log.e(LOG_TAG, "Error while fetching image", e);
|
||||
}
|
||||
throwable = e;
|
||||
}
|
||||
|
||||
if (bitmap == null) {
|
||||
if (throwable == null) {
|
||||
// Skia returned a null bitmap ... that's usually because
|
||||
// the given url wasn't pointing to a valid image
|
||||
throwable = new Exception("Skia image decoding failed");
|
||||
}
|
||||
h.sendMessage(Message.obtain(h, ON_FAIL, throwable));
|
||||
} else {
|
||||
h.sendMessage(Message.obtain(h, ON_END, bitmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ImageHandler extends Handler {
|
||||
|
||||
private String mUrl;
|
||||
private ImageLoaderCallback mCallback;
|
||||
|
||||
private ImageHandler(String url, ImageLoaderCallback callback) {
|
||||
mUrl = url;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
|
||||
switch (msg.what) {
|
||||
|
||||
case ON_START:
|
||||
if (mCallback != null) {
|
||||
mCallback.onImageLoadingStarted(ImageLoader.this);
|
||||
}
|
||||
break;
|
||||
|
||||
case ON_FAIL:
|
||||
if (mCallback != null) {
|
||||
mCallback.onImageLoadingFailed(ImageLoader.this, (Throwable) msg.obj);
|
||||
}
|
||||
break;
|
||||
|
||||
case ON_END:
|
||||
|
||||
final Bitmap bitmap = (Bitmap) msg.obj;
|
||||
sImageCache.put(mUrl, bitmap);
|
||||
|
||||
if (mCallback != null) {
|
||||
mCallback.onImageLoadingEnded(ImageLoader.this, bitmap);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.image;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
/**
|
||||
* An interface specifying a way to process an image prior storing it in the
|
||||
* application-wide cache. A great way to use this interface is to prepare a
|
||||
* Bitmap (resizing, adding rounded corners, changing the tint color, etc.) for
|
||||
* faster drawing.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public interface ImageProcessor {
|
||||
|
||||
/**
|
||||
* Called whenever the bitmap need to be processed. The returned may have
|
||||
* been modified or completely different.
|
||||
*
|
||||
* @param bitmap
|
||||
* The Bitmap to process
|
||||
* @return A Bitmap that has been modified
|
||||
*/
|
||||
Bitmap processImage(Bitmap bitmap);
|
||||
|
||||
}
|
||||
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.image;
|
||||
|
||||
import greendroid.image.ImageLoader.ImageLoaderCallback;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
/**
|
||||
* An {@link ImageRequest} may be used to request an image from the network. The
|
||||
* process of requesting for an image is done in three steps:
|
||||
* <ul>
|
||||
* <li>Instantiate a new {@link ImageRequest}</li>
|
||||
* <li>Call {@link #load(Context)} to start loading the image</li>
|
||||
* <li>Listen to loading state changes using a {@link ImageRequestCallback}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ImageRequest {
|
||||
|
||||
/**
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public static interface ImageRequestCallback {
|
||||
void onImageRequestStarted(ImageRequest request);
|
||||
|
||||
void onImageRequestFailed(ImageRequest request, Throwable throwable);
|
||||
|
||||
void onImageRequestEnded(ImageRequest request, Bitmap image);
|
||||
|
||||
void onImageRequestCancelled(ImageRequest request);
|
||||
}
|
||||
|
||||
private static ImageLoader sImageLoader;
|
||||
|
||||
private Future<?> mFuture;
|
||||
private String mUrl;
|
||||
private ImageRequestCallback mCallback;
|
||||
private ImageProcessor mBitmapProcessor;
|
||||
private BitmapFactory.Options mOptions;
|
||||
|
||||
public ImageRequest(String url, ImageRequestCallback callback) {
|
||||
this(url, callback, null);
|
||||
}
|
||||
|
||||
public ImageRequest(String url, ImageRequestCallback callback, ImageProcessor bitmapProcessor) {
|
||||
this(url, callback, bitmapProcessor, null);
|
||||
}
|
||||
|
||||
public ImageRequest(String url, ImageRequestCallback callback, ImageProcessor bitmapProcessor, BitmapFactory.Options options) {
|
||||
mUrl = url;
|
||||
mCallback = callback;
|
||||
mBitmapProcessor = bitmapProcessor;
|
||||
mOptions = options;
|
||||
}
|
||||
|
||||
public void setImageRequestCallback(ImageRequestCallback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
public void load(Context context) {
|
||||
if (mFuture == null) {
|
||||
if (sImageLoader == null) {
|
||||
sImageLoader = new ImageLoader(context);
|
||||
}
|
||||
mFuture = sImageLoader.loadImage(mUrl, new InnerCallback(), mBitmapProcessor, mOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
if (!isCancelled()) {
|
||||
// Here we do not want to force the task to be interrupted. Indeed,
|
||||
// it may be useful to keep the result in a cache for a further use
|
||||
mFuture.cancel(false);
|
||||
if (mCallback != null) {
|
||||
mCallback.onImageRequestCancelled(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isCancelled() {
|
||||
return mFuture.isCancelled();
|
||||
}
|
||||
|
||||
private class InnerCallback implements ImageLoaderCallback {
|
||||
|
||||
public void onImageLoadingStarted(ImageLoader loader) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onImageRequestStarted(ImageRequest.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onImageLoadingEnded(ImageLoader loader, Bitmap bitmap) {
|
||||
if (mCallback != null && !isCancelled()) {
|
||||
mCallback.onImageRequestEnded(ImageRequest.this, bitmap);
|
||||
}
|
||||
mFuture = null;
|
||||
}
|
||||
|
||||
public void onImageLoadingFailed(ImageLoader loader, Throwable exception) {
|
||||
if (mCallback != null && !isCancelled()) {
|
||||
mCallback.onImageRequestFailed(ImageRequest.this, exception);
|
||||
}
|
||||
mFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.util;
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public class Config {
|
||||
|
||||
private Config() {
|
||||
}
|
||||
|
||||
private static final int GD_LOG_LEVEL_INFO = 3;
|
||||
private static final int GD_LOG_LEVEL_WARNING = 2;
|
||||
private static final int GD_LOG_LEVEL_ERROR = 1;
|
||||
private static final int GD_LOG_LEVEL_NONE = 0;
|
||||
|
||||
/**
|
||||
* Set this flag to {@link Config#GD_LOG_LEVEL_NONE} when releasing your
|
||||
* application in order to remove all logs generated by GreenDroid.
|
||||
*/
|
||||
private static final int GD_LOG_LEVEL = GD_LOG_LEVEL_NONE;
|
||||
|
||||
public static final boolean GD_INFO_LOGS_ENABLED = (GD_LOG_LEVEL == GD_LOG_LEVEL_INFO);
|
||||
public static final boolean GD_WARNING_LOGS_ENABLED = GD_INFO_LOGS_ENABLED
|
||||
|| (GD_LOG_LEVEL == GD_LOG_LEVEL_WARNING);
|
||||
public static final boolean GD_ERROR_LOGS_ENABLED = GD_WARNING_LOGS_ENABLED || (GD_LOG_LEVEL == GD_LOG_LEVEL_ERROR);
|
||||
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.util;
|
||||
|
||||
import greendroid.app.GDApplication;
|
||||
import greendroid.image.ImageCache;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Class that provides several utility methods related to GreenDroid.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class GDUtils {
|
||||
|
||||
private GDUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current {@link GDApplication}
|
||||
*
|
||||
* @param context The calling context
|
||||
* @return The {@link GDApplication} the given context is linked to.
|
||||
*/
|
||||
public static GDApplication getGDApplication(Context context) {
|
||||
return (GDApplication) context.getApplicationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link GDApplication} image cache
|
||||
*
|
||||
* @param context The calling context
|
||||
* @return The image cache of the current {@link GDApplication}
|
||||
*/
|
||||
public static ImageCache getImageCache(Context context) {
|
||||
return getGDApplication(context).getImageCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link GDApplication} executors pool.
|
||||
*
|
||||
* @param context The calling context
|
||||
* @return The executors pool of the current {@link GDApplication}
|
||||
*/
|
||||
public static ExecutorService getExecutor(Context context) {
|
||||
return getGDApplication(context).getExecutor();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
package greendroid.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class Md5Util {
|
||||
|
||||
private static MessageDigest sMd5MessageDigest;
|
||||
private static StringBuilder sStringBuilder;
|
||||
|
||||
static {
|
||||
try {
|
||||
sMd5MessageDigest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO cyril: I'm quite sure about my "MD5" algorithm
|
||||
// but this is not a correct way to handle an exception ...
|
||||
}
|
||||
sStringBuilder = new StringBuilder();
|
||||
}
|
||||
|
||||
private Md5Util() {
|
||||
}
|
||||
|
||||
public static String md5(String s) {
|
||||
|
||||
sMd5MessageDigest.reset();
|
||||
sMd5MessageDigest.update(s.getBytes());
|
||||
|
||||
byte digest[] = sMd5MessageDigest.digest();
|
||||
|
||||
sStringBuilder.setLength(0);
|
||||
for (int i=0; i<digest.length; i++) {
|
||||
sStringBuilder.append(Integer.toHexString(0xFF & digest[i]));
|
||||
}
|
||||
|
||||
return sStringBuilder.toString();
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package greendroid.util;
|
||||
|
||||
/**
|
||||
* Utility class containing several useful constants related to time.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class Time {
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a second.
|
||||
*/
|
||||
public static final int GD_SECOND = 1000;
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a minute.
|
||||
*/
|
||||
public static final int GD_MINUTE = GD_SECOND * 60;
|
||||
|
||||
/**
|
||||
* The number of milliseconds in an hour.
|
||||
*/
|
||||
public static final int GD_HOUR = GD_MINUTE * 60;
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a day.
|
||||
*/
|
||||
public static final int GD_DAY = GD_HOUR * 24;
|
||||
|
||||
/**
|
||||
* The number of milliseconds in a week.
|
||||
*/
|
||||
public static final int GD_WEEK = GD_DAY * 7;
|
||||
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class ActionBarHost extends LinearLayout {
|
||||
|
||||
private GDActionBar mActionBar;
|
||||
private FrameLayout mContentView;
|
||||
|
||||
public ActionBarHost(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ActionBarHost(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mActionBar = (GDActionBar) findViewById(R.id.gd_action_bar);
|
||||
if (mActionBar == null || !(mActionBar instanceof GDActionBar)) {
|
||||
throw new IllegalArgumentException("No ActionBar with the id R.id.gd_action_bar found in the layout.");
|
||||
}
|
||||
|
||||
mContentView = (FrameLayout) findViewById(R.id.gd_action_bar_content_view);
|
||||
if (mContentView == null || !(mContentView instanceof FrameLayout)) {
|
||||
throw new IllegalArgumentException("No FrameLayout with the id R.id.gd_action_bar_content_view found in the layout.");
|
||||
}
|
||||
}
|
||||
|
||||
public GDActionBar getActionBar() {
|
||||
return mActionBar;
|
||||
}
|
||||
|
||||
public FrameLayout getContentView() {
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,297 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import greendroid.graphics.drawable.ActionBarDrawable;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Base class representing an {@link ActionBarItem} used in {@link GDActionBar}s.
|
||||
* The base implementation exposes a single Drawable as well as a content
|
||||
* description.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public abstract class ActionBarItem {
|
||||
|
||||
public enum Type {
|
||||
GoHome, // A house
|
||||
Search, // A magnifying glass
|
||||
Talk, // A speech bubble
|
||||
Compose, // A sheet of paper with a pen
|
||||
Export, // A dot with an arrow
|
||||
Share, // A dot with two arrows
|
||||
Refresh, // Two curved arrows
|
||||
TakePhoto, // A camera
|
||||
// PickPhoto, // Two pictures with an arrow
|
||||
Locate, // The traditional GMaps pin
|
||||
Edit, // A pencil
|
||||
Add, // A plus sign
|
||||
Star, // A star
|
||||
SortBySize, // Some bars
|
||||
LocateMyself, // A surrounded dot
|
||||
Compass,
|
||||
Help,
|
||||
Info,
|
||||
Settings,
|
||||
List,
|
||||
Trashcan,
|
||||
Eye,
|
||||
AllFriends,
|
||||
Group,
|
||||
Gallery,
|
||||
Slideshow,
|
||||
Mail
|
||||
}
|
||||
|
||||
protected Drawable mDrawable;
|
||||
|
||||
protected CharSequence mContentDescription;
|
||||
protected View mItemView;
|
||||
|
||||
protected Context mContext;
|
||||
protected GDActionBar mActionBar;
|
||||
|
||||
private int mItemId;
|
||||
|
||||
void setActionBar(GDActionBar actionBar) {
|
||||
mContext = actionBar.getContext();
|
||||
mActionBar = actionBar;
|
||||
}
|
||||
|
||||
public Drawable getDrawable() {
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
public ActionBarItem setDrawable(int drawableId) {
|
||||
return setDrawable(mContext.getResources().getDrawable(drawableId));
|
||||
}
|
||||
|
||||
public ActionBarItem setDrawable(Drawable drawable) {
|
||||
if (drawable != mDrawable) {
|
||||
mDrawable = drawable;
|
||||
if (mItemView != null) {
|
||||
onDrawableChanged();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public CharSequence getContentDescription() {
|
||||
return mContentDescription;
|
||||
}
|
||||
|
||||
public ActionBarItem setContentDescription(int contentDescriptionId) {
|
||||
return setContentDescription(mContext.getString(contentDescriptionId));
|
||||
}
|
||||
|
||||
public ActionBarItem setContentDescription(CharSequence contentDescription) {
|
||||
if (contentDescription != mContentDescription) {
|
||||
mContentDescription = contentDescription;
|
||||
if (mItemView != null) {
|
||||
onContentDescriptionChanged();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public View getItemView() {
|
||||
if (mItemView == null) {
|
||||
mItemView = createItemView();
|
||||
prepareItemView();
|
||||
}
|
||||
return mItemView;
|
||||
}
|
||||
|
||||
protected abstract View createItemView();
|
||||
|
||||
protected void prepareItemView() {
|
||||
}
|
||||
|
||||
protected void onDrawableChanged() {
|
||||
}
|
||||
|
||||
protected void onContentDescriptionChanged() {
|
||||
}
|
||||
|
||||
protected void onItemClicked() {
|
||||
}
|
||||
|
||||
void setItemId(int itemId) {
|
||||
mItemId = itemId;
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return mItemId;
|
||||
}
|
||||
|
||||
static ActionBarItem createWithType(GDActionBar actionBar, ActionBarItem.Type type) {
|
||||
|
||||
int drawableId = 0;
|
||||
int descriptionId = 0;
|
||||
|
||||
switch (type) {
|
||||
case GoHome:
|
||||
drawableId = R.drawable.gd_action_bar_home;
|
||||
descriptionId = R.string.gd_go_home;
|
||||
break;
|
||||
|
||||
case Search:
|
||||
drawableId = R.drawable.gd_action_bar_search;
|
||||
descriptionId = R.string.gd_search;
|
||||
break;
|
||||
|
||||
case Talk:
|
||||
drawableId = R.drawable.gd_action_bar_talk;
|
||||
descriptionId = R.string.gd_talk;
|
||||
break;
|
||||
|
||||
case Compose:
|
||||
drawableId = R.drawable.gd_action_bar_compose;
|
||||
descriptionId = R.string.gd_compose;
|
||||
break;
|
||||
|
||||
case Export:
|
||||
drawableId = R.drawable.gd_action_bar_export;
|
||||
descriptionId = R.string.gd_export;
|
||||
break;
|
||||
|
||||
case Share:
|
||||
drawableId = R.drawable.gd_action_bar_share;
|
||||
descriptionId = R.string.gd_share;
|
||||
break;
|
||||
|
||||
case Refresh:
|
||||
return actionBar.newActionBarItem(LoaderActionBarItem.class)
|
||||
.setDrawable(new ActionBarDrawable(actionBar.getResources(), R.drawable.gd_action_bar_refresh))
|
||||
.setContentDescription(R.string.gd_refresh);
|
||||
|
||||
case TakePhoto:
|
||||
drawableId = R.drawable.gd_action_bar_take_photo;
|
||||
descriptionId = R.string.gd_take_photo;
|
||||
break;
|
||||
//
|
||||
// case PickPhoto:
|
||||
// drawableId = R.drawable.gd_action_bar_pick_photo;
|
||||
// descriptionId = R.string.gd_pick_photo;
|
||||
// break;
|
||||
|
||||
case Locate:
|
||||
drawableId = R.drawable.gd_action_bar_locate;
|
||||
descriptionId = R.string.gd_locate;
|
||||
break;
|
||||
|
||||
case Edit:
|
||||
drawableId = R.drawable.gd_action_bar_edit;
|
||||
descriptionId = R.string.gd_edit;
|
||||
break;
|
||||
|
||||
case Add:
|
||||
drawableId = R.drawable.gd_action_bar_add;
|
||||
descriptionId = R.string.gd_add;
|
||||
break;
|
||||
|
||||
case Star:
|
||||
drawableId = R.drawable.gd_action_bar_star;
|
||||
descriptionId = R.string.gd_star;
|
||||
break;
|
||||
|
||||
case SortBySize:
|
||||
drawableId = R.drawable.gd_action_bar_sort_by_size;
|
||||
descriptionId = R.string.gd_sort_by_size;
|
||||
break;
|
||||
|
||||
case LocateMyself:
|
||||
drawableId = R.drawable.gd_action_bar_locate_myself;
|
||||
descriptionId = R.string.gd_locate_myself;
|
||||
break;
|
||||
|
||||
case Compass:
|
||||
drawableId = R.drawable.gd_action_bar_compass;
|
||||
descriptionId = R.string.gd_compass;
|
||||
break;
|
||||
|
||||
case Help:
|
||||
drawableId = R.drawable.gd_action_bar_help;
|
||||
descriptionId = R.string.gd_help;
|
||||
break;
|
||||
|
||||
case Info:
|
||||
drawableId = R.drawable.gd_action_bar_info;
|
||||
descriptionId = R.string.gd_info;
|
||||
break;
|
||||
|
||||
case Settings:
|
||||
drawableId = R.drawable.gd_action_bar_settings;
|
||||
descriptionId = R.string.gd_settings;
|
||||
break;
|
||||
|
||||
case List:
|
||||
drawableId = R.drawable.gd_action_bar_list;
|
||||
descriptionId = R.string.gd_list;
|
||||
break;
|
||||
|
||||
case Trashcan:
|
||||
drawableId = R.drawable.gd_action_bar_trashcan;
|
||||
descriptionId = R.string.gd_trashcan;
|
||||
break;
|
||||
|
||||
case Eye:
|
||||
drawableId = R.drawable.gd_action_bar_eye;
|
||||
descriptionId = R.string.gd_eye;
|
||||
break;
|
||||
|
||||
case AllFriends:
|
||||
drawableId = R.drawable.gd_action_bar_all_friends;
|
||||
descriptionId = R.string.gd_all_friends;
|
||||
break;
|
||||
|
||||
case Group:
|
||||
drawableId = R.drawable.gd_action_bar_group;
|
||||
descriptionId = R.string.gd_group;
|
||||
break;
|
||||
|
||||
case Gallery:
|
||||
drawableId = R.drawable.gd_action_bar_gallery;
|
||||
descriptionId = R.string.gd_gallery;
|
||||
break;
|
||||
|
||||
case Slideshow:
|
||||
drawableId = R.drawable.gd_action_bar_slideshow;
|
||||
descriptionId = R.string.gd_slideshow;
|
||||
break;
|
||||
|
||||
case Mail:
|
||||
drawableId = R.drawable.gd_action_bar_mail;
|
||||
descriptionId = R.string.gd_mail;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Do nothing but return null
|
||||
return null;
|
||||
}
|
||||
|
||||
final Drawable d = new ActionBarDrawable(actionBar.getResources(), drawableId);
|
||||
|
||||
return actionBar.newActionBarItem(NormalActionBarItem.class).setDrawable(d)
|
||||
.setContentDescription(descriptionId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,466 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import greendroid.image.ImageProcessor;
|
||||
import greendroid.image.ImageRequest;
|
||||
import greendroid.image.ImageRequest.ImageRequestCallback;
|
||||
import greendroid.util.Config;
|
||||
import greendroid.util.GDUtils;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapFactory.Options;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link AsyncImageView} is a network-aware {@link ImageView}. It may display
|
||||
* images from the web according to a URL. {@link AsyncImageView} takes care of
|
||||
* loading asynchronously images on the Internet. It also caches images in an
|
||||
* application-wide cache to prevent loading images several times.
|
||||
* </p>
|
||||
* <p>
|
||||
* Clients may listen the {@link OnImageViewLoadListener} to be notified of the
|
||||
* current image loading state.
|
||||
* </p>
|
||||
* <p>
|
||||
* {@link AsyncImageView} may be extremely useful in {@link ListView}'s row. To
|
||||
* prevent your {@link AsyncImageView} from downloading while scrolling or
|
||||
* flinging it is a good idea to pause it using {@link #setPaused(boolean)}
|
||||
* method. Once the scrolling/flinging is over, <em>un-pause</em> your
|
||||
* {@link AsyncImageView}s using <code>setPaused(false)</code>
|
||||
* </p>
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class AsyncImageView extends ImageView implements ImageRequestCallback {
|
||||
|
||||
private static final String LOG_TAG = AsyncImageView.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Clients may listen to {@link AsyncImageView} changes using a
|
||||
* {@link OnImageViewLoadListener}.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public static interface OnImageViewLoadListener {
|
||||
|
||||
/**
|
||||
* Called when the image started to load
|
||||
*
|
||||
* @param imageView
|
||||
* The AsyncImageView that started loading
|
||||
*/
|
||||
void onLoadingStarted(AsyncImageView imageView);
|
||||
|
||||
/**
|
||||
* Called when the image ended to load that is when the image has been
|
||||
* downloaded and is ready to be displayed on screen
|
||||
*
|
||||
* @param imageView
|
||||
* The AsyncImageView that ended loading
|
||||
*/
|
||||
void onLoadingEnded(AsyncImageView imageView, Bitmap image);
|
||||
|
||||
/**
|
||||
* Called when the image loading failed
|
||||
*
|
||||
* @param imageView
|
||||
* The AsyncImageView that failed to load
|
||||
*/
|
||||
void onLoadingFailed(AsyncImageView imageView, Throwable throwable);
|
||||
}
|
||||
|
||||
private static final int IMAGE_SOURCE_UNKNOWN = -1;
|
||||
private static final int IMAGE_SOURCE_RESOURCE = 0;
|
||||
private static final int IMAGE_SOURCE_DRAWABLE = 1;
|
||||
private static final int IMAGE_SOURCE_BITMAP = 2;
|
||||
|
||||
private int mImageSource;
|
||||
private Bitmap mDefaultBitmap;
|
||||
private Drawable mDefaultDrawable;
|
||||
private int mDefaultResId;
|
||||
|
||||
private String mUrl;
|
||||
private ImageRequest mRequest;
|
||||
private boolean mPaused;
|
||||
|
||||
private Bitmap mBitmap;
|
||||
private OnImageViewLoadListener mOnImageViewLoadListener;
|
||||
private ImageProcessor mImageProcessor;
|
||||
private BitmapFactory.Options mOptions;
|
||||
|
||||
public AsyncImageView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public AsyncImageView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public AsyncImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
initializeDefaultValues();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.AsyncImageView);
|
||||
|
||||
setUrl(a.getString(R.styleable.AsyncImageView_url));
|
||||
|
||||
Drawable d = a.getDrawable(R.styleable.AsyncImageView_defaultSrc);
|
||||
if (d != null) {
|
||||
setDefaultImageDrawable(d);
|
||||
}
|
||||
|
||||
final int inDensity = a.getInt(R.styleable.AsyncImageView_inDensity, -1);
|
||||
if (inDensity != -1) {
|
||||
setInDensity(inDensity);
|
||||
}
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void initializeDefaultValues() {
|
||||
mImageSource = IMAGE_SOURCE_UNKNOWN;
|
||||
mPaused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this AsyncImageView is currently loading an image.
|
||||
*
|
||||
* @return true if this AsyncImageView is currently loading an image.
|
||||
* Otherwise it returns false.
|
||||
*/
|
||||
public boolean isLoading() {
|
||||
return mRequest != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the displayed image has been correctly loaded.
|
||||
*
|
||||
* @return true if this AsyncImageView succeed to load the image at the
|
||||
* given url.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return mRequest == null && mBitmap != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause this AsyncImageView preventing it from downloading the image. The
|
||||
* download process will start back once setPaused(false) is called.
|
||||
*
|
||||
* @param paused
|
||||
*/
|
||||
public void setPaused(boolean paused) {
|
||||
if (mPaused != paused) {
|
||||
mPaused = paused;
|
||||
if (!paused) {
|
||||
reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to {@link #setBitmapFactoryOptions(Options)} that simply
|
||||
* sets the inDensity for loaded image.
|
||||
*
|
||||
* @param inDensity
|
||||
* @see AsyncImageView#setBitmapFactoryOptions(Options)
|
||||
*/
|
||||
public void setInDensity(int inDensity) {
|
||||
if (mOptions == null) {
|
||||
mOptions = new BitmapFactory.Options();
|
||||
mOptions.inDither = true;
|
||||
mOptions.inScaled = true;
|
||||
mOptions.inTargetDensity = getContext().getResources().getDisplayMetrics().densityDpi;
|
||||
}
|
||||
|
||||
mOptions.inDensity = inDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a {@link Options} object to this {@link AsyncImageView}. Those
|
||||
* options are used internally by the {@link AsyncImageView} when decoding
|
||||
* the image. This may be used to prevent the default behavior that loads
|
||||
* all images as mdpi density.
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
public void setOptions(BitmapFactory.Options options) {
|
||||
mOptions = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the image pointed by the given URL
|
||||
*/
|
||||
public void reload() {
|
||||
reload(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload the image pointed by the given URL. You may want to force
|
||||
* reloading by setting the force parameter to true.
|
||||
*
|
||||
* @param force
|
||||
* if true the AsyncImageView won't look into the
|
||||
* application-wide cache.
|
||||
*/
|
||||
public void reload(boolean force) {
|
||||
if (mRequest == null && mUrl != null) {
|
||||
|
||||
// Prior downloading the image ... let's look in a cache !
|
||||
// TODO cyril: This is a synchronous call ... make it asynchronous
|
||||
mBitmap = null;
|
||||
if (!force) {
|
||||
mBitmap = GDUtils.getImageCache(getContext()).get(mUrl);
|
||||
}
|
||||
|
||||
if (mBitmap != null) {
|
||||
setImageBitmap(mBitmap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.i(LOG_TAG,
|
||||
"Cache miss. Starting to load the image at the given URL");
|
||||
}
|
||||
|
||||
setDefaultImage();
|
||||
mRequest = new ImageRequest(mUrl, this, mImageProcessor, mOptions);
|
||||
mRequest.load(getContext());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the loading to be stopped.
|
||||
*/
|
||||
public void stopLoading() {
|
||||
if (mRequest != null) {
|
||||
mRequest.cancel();
|
||||
mRequest = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when an event occured for this
|
||||
* AsyncImageView.
|
||||
*
|
||||
* @param listener
|
||||
* The listener that will be notified
|
||||
*/
|
||||
public void setOnImageViewLoadListener(OnImageViewLoadListener listener) {
|
||||
mOnImageViewLoadListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the url of the image that will be used as the content of this
|
||||
* AsyncImageView. The given may be null in order to display the default
|
||||
* image. Please note the url may be a local url. For instance, you can
|
||||
* asynchronously load images from the disk memory is the url scheme is
|
||||
* <code>file://</code>
|
||||
*
|
||||
* @param url
|
||||
* The url of the image to set. Pass null to force the
|
||||
* AsyncImageView to display the default image
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
|
||||
// Check the url has changed
|
||||
if (mBitmap != null && url != null && url.equals(mUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
stopLoading();
|
||||
mUrl = url;
|
||||
|
||||
// Setting the url to an empty string force the displayed image to the
|
||||
// default image
|
||||
if (TextUtils.isEmpty(mUrl)) {
|
||||
mBitmap = null;
|
||||
setDefaultImage();
|
||||
} else {
|
||||
if (!mPaused) {
|
||||
reload();
|
||||
} else {
|
||||
// We're paused: let's look in a synchronous and efficient cache
|
||||
// prior using the default image.
|
||||
mBitmap = GDUtils.getImageCache(getContext()).get(mUrl);
|
||||
if (mBitmap != null) {
|
||||
setImageBitmap(mBitmap);
|
||||
return;
|
||||
} else {
|
||||
setDefaultImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default bitmap as the content of this AsyncImageView
|
||||
*
|
||||
* @param bitmap
|
||||
* The bitmap to set
|
||||
*/
|
||||
public void setDefaultImageBitmap(Bitmap bitmap) {
|
||||
mImageSource = IMAGE_SOURCE_BITMAP;
|
||||
mDefaultBitmap = bitmap;
|
||||
setDefaultImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default drawable as the content of this AsyncImageView
|
||||
*
|
||||
* @param drawable
|
||||
* The drawable to set
|
||||
*/
|
||||
public void setDefaultImageDrawable(Drawable drawable) {
|
||||
mImageSource = IMAGE_SOURCE_DRAWABLE;
|
||||
mDefaultDrawable = drawable;
|
||||
setDefaultImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default resource as the content of this AsyncImageView
|
||||
*
|
||||
* @param resId
|
||||
* The resource identifier to set
|
||||
*/
|
||||
public void setDefaultImageResource(int resId) {
|
||||
mImageSource = IMAGE_SOURCE_RESOURCE;
|
||||
mDefaultResId = resId;
|
||||
setDefaultImage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an image processor to this AsyncImageView. An ImageProcessor may be
|
||||
* used in order to work on the retrieved Bitmap prior displaying it on
|
||||
* screen.
|
||||
*
|
||||
* @param imageProcessor
|
||||
* The {@link ImageProcessor} to set
|
||||
* @see ImageProcessor
|
||||
*/
|
||||
public void setImageProcessor(ImageProcessor imageProcessor) {
|
||||
mImageProcessor = imageProcessor;
|
||||
}
|
||||
|
||||
private void setDefaultImage() {
|
||||
if (mBitmap == null) {
|
||||
switch (mImageSource) {
|
||||
case IMAGE_SOURCE_BITMAP:
|
||||
setImageBitmap(mDefaultBitmap);
|
||||
break;
|
||||
case IMAGE_SOURCE_DRAWABLE:
|
||||
setImageDrawable(mDefaultDrawable);
|
||||
break;
|
||||
case IMAGE_SOURCE_RESOURCE:
|
||||
setImageResource(mDefaultResId);
|
||||
break;
|
||||
default:
|
||||
setImageDrawable(null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SavedState extends BaseSavedState {
|
||||
String url;
|
||||
|
||||
SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
private SavedState(Parcel in) {
|
||||
super(in);
|
||||
url = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeString(url);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
|
||||
public SavedState createFromParcel(Parcel in) {
|
||||
return new SavedState(in);
|
||||
}
|
||||
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
Parcelable superState = super.onSaveInstanceState();
|
||||
SavedState ss = new SavedState(superState);
|
||||
|
||||
ss.url = mUrl;
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState ss = (SavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
|
||||
setUrl(ss.url);
|
||||
}
|
||||
|
||||
public void onImageRequestStarted(ImageRequest request) {
|
||||
if (mOnImageViewLoadListener != null) {
|
||||
mOnImageViewLoadListener.onLoadingStarted(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onImageRequestFailed(ImageRequest request, Throwable throwable) {
|
||||
mRequest = null;
|
||||
if (mOnImageViewLoadListener != null) {
|
||||
mOnImageViewLoadListener.onLoadingFailed(this, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public void onImageRequestEnded(ImageRequest request, Bitmap image) {
|
||||
mBitmap = image;
|
||||
setImageBitmap(image);
|
||||
if (mOnImageViewLoadListener != null) {
|
||||
mOnImageViewLoadListener.onLoadingEnded(this, image);
|
||||
}
|
||||
mRequest = null;
|
||||
}
|
||||
|
||||
public void onImageRequestCancelled(ImageRequest request) {
|
||||
mRequest = null;
|
||||
if (mOnImageViewLoadListener != null) {
|
||||
mOnImageViewLoadListener.onLoadingFailed(this, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import greendroid.graphics.drawable.ActionBarDrawable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class GDActionBar extends LinearLayout {
|
||||
|
||||
public static final int NONE = 0;
|
||||
private static final int MAX_ITEMS_COUNT = 3;
|
||||
|
||||
public enum Type {
|
||||
Normal, Dashboard, Empty
|
||||
}
|
||||
|
||||
public interface OnActionBarListener {
|
||||
|
||||
int HOME_ITEM = -1;
|
||||
|
||||
/**
|
||||
* Clients may listen to this method in order to be notified the user
|
||||
* has clicked on an item.
|
||||
*
|
||||
* @param position The position of the item in the action bar. -1 means
|
||||
* the user pressed the "Home" button. 0 means the user
|
||||
* clicked the first action bar item (the leftmost item) and
|
||||
* so on.
|
||||
*/
|
||||
void onActionBarItemClicked(int position);
|
||||
}
|
||||
|
||||
private TextView mTitleView;
|
||||
private ImageButton mHomeButton;
|
||||
|
||||
private boolean mMerging = false;
|
||||
|
||||
private CharSequence mTitle;
|
||||
private GDActionBar.Type mType;
|
||||
private OnActionBarListener mOnActionBarListener;
|
||||
private LinkedList<ActionBarItem> mItems;
|
||||
|
||||
private Drawable mDividerDrawable;
|
||||
private Drawable mHomeDrawable;
|
||||
private int mDividerWidth;
|
||||
|
||||
public GDActionBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public GDActionBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.gdActionBarStyle);
|
||||
}
|
||||
|
||||
public GDActionBar(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs);
|
||||
|
||||
initActionBar();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar, defStyle, 0);
|
||||
|
||||
mTitle = a.getString(R.styleable.ActionBar_gdtitle);
|
||||
|
||||
mDividerDrawable = a.getDrawable(R.styleable.ActionBar_dividerDrawable);
|
||||
mDividerWidth = a.getDimensionPixelSize(R.styleable.ActionBar_dividerWidth, -1);
|
||||
mHomeDrawable = a.getDrawable(R.styleable.ActionBar_homeDrawable);
|
||||
if (mHomeDrawable == null) {
|
||||
mHomeDrawable = new ActionBarDrawable(getResources(), R.drawable.gd_action_bar_home);
|
||||
}
|
||||
|
||||
int layoutID;
|
||||
int type = a.getInteger(R.styleable.ActionBar_type, -1);
|
||||
switch (type) {
|
||||
case 2:
|
||||
mType = Type.Empty;
|
||||
layoutID = R.layout.gd_action_bar_empty;
|
||||
break;
|
||||
case 1:
|
||||
mType = Type.Dashboard;
|
||||
layoutID = R.layout.gd_action_bar_dashboard;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
mType = Type.Normal;
|
||||
layoutID = R.layout.gd_action_bar_normal;
|
||||
break;
|
||||
}
|
||||
|
||||
// HACK Cyril: Without this, the onFinishInflate is called twice !?!
|
||||
// This issue is due to a bug when Android inflates a layout with a
|
||||
// parent - which is compulsory with a <merge /> tag. I've reported this
|
||||
// bug to Romain Guy who fixed it (patch will probably be available in
|
||||
// the Gingerbread release).
|
||||
mMerging = true;
|
||||
LayoutInflater.from(context).inflate(layoutID, this);
|
||||
mMerging = false;
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void initActionBar() {
|
||||
mItems = new LinkedList<ActionBarItem>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
if (!mMerging) {
|
||||
|
||||
switch (mType) {
|
||||
case Dashboard:
|
||||
mHomeButton = (ImageButton) findViewById(R.id.gd_action_bar_home_item);
|
||||
mHomeButton.setOnClickListener(mClickHandler);
|
||||
break;
|
||||
|
||||
case Empty:
|
||||
mTitleView = (TextView) findViewById(R.id.gd_action_bar_title);
|
||||
setTitle(mTitle);
|
||||
break;
|
||||
|
||||
case Normal:
|
||||
default:
|
||||
mHomeButton = (ImageButton) findViewById(R.id.gd_action_bar_home_item);
|
||||
mHomeButton.setOnClickListener(mClickHandler);
|
||||
mHomeButton.setImageDrawable(mHomeDrawable);
|
||||
mHomeButton.setContentDescription(getContext().getString(R.string.gd_go_home));
|
||||
mTitleView = (TextView) findViewById(R.id.gd_action_bar_title);
|
||||
setTitle(mTitle);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnActionBarListener(OnActionBarListener listener) {
|
||||
mOnActionBarListener = listener;
|
||||
}
|
||||
|
||||
public void setTitle(CharSequence title) {
|
||||
mTitle = title;
|
||||
if (mTitleView != null) {
|
||||
mTitleView.setText(title);
|
||||
}
|
||||
}
|
||||
|
||||
public ActionBarItem addItem(ActionBarItem.Type actionBarItemType) {
|
||||
return addItem(ActionBarItem.createWithType(this, actionBarItemType), NONE);
|
||||
}
|
||||
|
||||
public ActionBarItem addItem(ActionBarItem.Type actionBarItemType, int itemId) {
|
||||
return addItem(ActionBarItem.createWithType(this, actionBarItemType), itemId);
|
||||
}
|
||||
|
||||
public ActionBarItem addItem(ActionBarItem item) {
|
||||
return addItem(item, NONE);
|
||||
}
|
||||
|
||||
public ActionBarItem addItem(ActionBarItem item, int itemId) {
|
||||
|
||||
if (mItems.size() >= MAX_ITEMS_COUNT) {
|
||||
/*
|
||||
* An ActionBar must contain as few items as possible. So let's keep
|
||||
* a limit :)
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item != null) {
|
||||
|
||||
item.setItemId(itemId);
|
||||
|
||||
if (mDividerDrawable != null) {
|
||||
ImageView divider = new ImageView(getContext());
|
||||
int dividerWidth = (mDividerWidth > 0) ? mDividerWidth : mDividerDrawable.getIntrinsicWidth();
|
||||
final LinearLayout.LayoutParams lp = new LayoutParams(dividerWidth, LayoutParams.FILL_PARENT);
|
||||
divider.setLayoutParams(lp);
|
||||
divider.setBackgroundDrawable(mDividerDrawable);
|
||||
addView(divider);
|
||||
}
|
||||
|
||||
final View itemView = item.getItemView();
|
||||
itemView.findViewById(R.id.gd_action_bar_item).setOnClickListener(mClickHandler);
|
||||
|
||||
final int size = (int) getResources().getDimension(R.dimen.gd_action_bar_height);
|
||||
addView(itemView, new LayoutParams(size, LayoutParams.FILL_PARENT));
|
||||
|
||||
mItems.add(item);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public ActionBarItem getItem(int position) {
|
||||
if (position < 0 || position >= mItems.size()) {
|
||||
return null;
|
||||
}
|
||||
return mItems.get(position);
|
||||
}
|
||||
|
||||
public void removeItem(ActionBarItem item) {
|
||||
removeItem(mItems.indexOf(item));
|
||||
}
|
||||
|
||||
public void removeItem(int position) {
|
||||
|
||||
if (position < 0 || position >= mItems.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int viewIndex = indexOfChild(mItems.get(position).getItemView());
|
||||
final int increment = (mDividerDrawable != null) ? 1 : 0;
|
||||
removeViews(viewIndex - increment, 1 + increment);
|
||||
mItems.remove(position);
|
||||
}
|
||||
|
||||
public void setType(Type type) {
|
||||
if (type != mType) {
|
||||
|
||||
removeAllViews();
|
||||
|
||||
int layoutId = 0;
|
||||
switch (type) {
|
||||
case Empty:
|
||||
layoutId = R.layout.gd_action_bar_empty;
|
||||
break;
|
||||
case Dashboard:
|
||||
layoutId = R.layout.gd_action_bar_dashboard;
|
||||
break;
|
||||
case Normal:
|
||||
layoutId = R.layout.gd_action_bar_normal;
|
||||
break;
|
||||
}
|
||||
|
||||
mType = type;
|
||||
LayoutInflater.from(getContext()).inflate(layoutId, this);
|
||||
|
||||
// Reset all items
|
||||
LinkedList<ActionBarItem> itemsCopy = new LinkedList<ActionBarItem>(mItems);
|
||||
mItems.clear();
|
||||
for (ActionBarItem item : itemsCopy) {
|
||||
addItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ActionBarItem newActionBarItem(Class<? extends ActionBarItem> klass) {
|
||||
try {
|
||||
ActionBarItem item = klass.newInstance();
|
||||
item.setActionBar(this);
|
||||
return item;
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("The given klass must have a default constructor");
|
||||
}
|
||||
}
|
||||
|
||||
private OnClickListener mClickHandler = new OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
if (mOnActionBarListener != null) {
|
||||
|
||||
if (v == mHomeButton) {
|
||||
mOnActionBarListener.onActionBarItemClicked(OnActionBarListener.HOME_ITEM);
|
||||
return;
|
||||
}
|
||||
|
||||
final int itemCount = mItems.size();
|
||||
for (int i = 0; i < itemCount; i++) {
|
||||
final ActionBarItem item = mItems.get(i);
|
||||
final View itemButton = item.getItemView().findViewById(R.id.gd_action_bar_item);
|
||||
if (v == itemButton) {
|
||||
item.onItemClicked();
|
||||
mOnActionBarListener.onActionBarItemClicked(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,453 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import greendroid.widget.item.DescriptionItem;
|
||||
import greendroid.widget.item.DrawableItem;
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.LongTextItem;
|
||||
import greendroid.widget.item.ProgressItem;
|
||||
import greendroid.widget.item.SeparatorItem;
|
||||
import greendroid.widget.item.SubtextItem;
|
||||
import greendroid.widget.item.SubtitleItem;
|
||||
import greendroid.widget.item.TextItem;
|
||||
import greendroid.widget.item.ThumbnailItem;
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Xml;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link ListAdapter} that acts like an {@link ArrayAdapter}. It manages a
|
||||
* ListView that is backed by an array of {@link Item}s. This is more advanced
|
||||
* than a simple {@link ArrayAdapter} because it handles different types of
|
||||
* cells internally. Adding, removing items from the internal array is also
|
||||
* possible.
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link ListView} can be notified manually using
|
||||
* {@link notifyDataSetChanged} or automatically using the notifyOnChange flag.
|
||||
* </p>
|
||||
* <p>
|
||||
* Finally, an ItemAdapter can be created via XML code using the createFromXml
|
||||
* method. This is a very powerful feature when you want to display static data
|
||||
* or if you want to prepopulate your ItemAdapter.
|
||||
* </p>
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ItemAdapter extends BaseAdapter {
|
||||
|
||||
private static final int DEFAULT_MAX_VIEW_TYPE_COUNT = 10;
|
||||
|
||||
private static class TypeInfo {
|
||||
int count;
|
||||
int type;
|
||||
}
|
||||
|
||||
private List<Item> mItems;
|
||||
private HashMap<Class<? extends Item>, TypeInfo> mTypes;
|
||||
private Context mContext;
|
||||
|
||||
private boolean mNotifyOnChange;
|
||||
private int mMaxViewTypeCount;
|
||||
|
||||
/**
|
||||
* Constructs an empty ItemAdapter.
|
||||
*
|
||||
* @param context The context associated with this array adapter.
|
||||
*/
|
||||
public ItemAdapter(Context context) {
|
||||
this(context, new ArrayList<Item>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ItemAdapter using the specified items.
|
||||
* <p>
|
||||
* <em>Note</em> : Using this constructor implies the internal array will be
|
||||
* immutable. As a result, adding or removing items will result in an
|
||||
* exception.
|
||||
* </p>
|
||||
*
|
||||
* @param context The context associated with this array adapter.
|
||||
* @param items The array of Items use as underlying data for this
|
||||
* ItemAdapter
|
||||
*/
|
||||
public ItemAdapter(Context context, Item[] items) {
|
||||
this(context, Arrays.asList(items), DEFAULT_MAX_VIEW_TYPE_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ItemAdapter using the specified items.
|
||||
* <p>
|
||||
*
|
||||
* @param context The context associated with this array adapter.
|
||||
* @param items The list of Items used as data for this ItemAdapter
|
||||
*/
|
||||
public ItemAdapter(Context context, List<Item> items) {
|
||||
this(context, items, DEFAULT_MAX_VIEW_TYPE_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ItemAdapter using the specified items.
|
||||
* <p>
|
||||
* <em>Note</em> : Using this constructor implies the internal array will be
|
||||
* immutable. As a result, adding or removing items will result in an
|
||||
* exception.
|
||||
* </p>
|
||||
* <p>
|
||||
* <em><strong>Note:</strong> A ListAdapter doesn't handle variable view type
|
||||
* count (even after a notifyDataSetChanged). An ItemAdapter handles several
|
||||
* types of cell are therefore use a trick to overcome the previous problem.
|
||||
* This trick is to fool the ListView several types exist. If you already
|
||||
* know the number of item types you can have, simply set it using this method</em>
|
||||
* </p>
|
||||
*
|
||||
* @param context The context associated with this array adapter.
|
||||
* @param items The array of Items use as underlying data for this
|
||||
* ItemAdapter
|
||||
* @param maxViewTypeCount The maximum number of view type that may be
|
||||
* generated by this ItemAdapter
|
||||
*/
|
||||
public ItemAdapter(Context context, Item[] items, int maxViewTypeCount) {
|
||||
this(context, Arrays.asList(items), maxViewTypeCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ItemAdapter using the specified items.
|
||||
* <p>
|
||||
* <em><strong>Note:</strong> A ListAdapter doesn't handle variable view type
|
||||
* count (even after a notifyDataSetChanged). An ItemAdapter handles several
|
||||
* types of cell are therefore use a trick to overcome the previous problem.
|
||||
* This trick is to fool the ListView several types exist. If you already
|
||||
* know the number of item types you can have, simply set it using this method</em>
|
||||
* </p>
|
||||
*
|
||||
* @param context The context associated with this array adapter.
|
||||
* @param items The list of Items used as data for this ItemAdapter
|
||||
* @param maxViewTypeCount The maximum number of view type that may be
|
||||
* generated by this ItemAdapter
|
||||
*/
|
||||
public ItemAdapter(Context context, List<Item> items, int maxViewTypeCount) {
|
||||
mContext = context;
|
||||
mItems = items;
|
||||
mTypes = new HashMap<Class<? extends Item>, TypeInfo>();
|
||||
mMaxViewTypeCount = Integer.MAX_VALUE;
|
||||
|
||||
for (Item item : mItems) {
|
||||
addItem(item);
|
||||
}
|
||||
|
||||
mMaxViewTypeCount = Math.max(1, Math.max(mTypes.size(), maxViewTypeCount));
|
||||
}
|
||||
|
||||
private void addItem(Item item) {
|
||||
final Class<? extends Item> klass = item.getClass();
|
||||
TypeInfo info = mTypes.get(klass);
|
||||
|
||||
if (info == null) {
|
||||
final int type = mTypes.size();
|
||||
if (type >= mMaxViewTypeCount) {
|
||||
throw new RuntimeException("This ItemAdapter may handle only " + mMaxViewTypeCount
|
||||
+ " different view types.");
|
||||
}
|
||||
final TypeInfo newInfo = new TypeInfo();
|
||||
newInfo.count = 1;
|
||||
newInfo.type = type;
|
||||
mTypes.put(klass, newInfo);
|
||||
} else {
|
||||
info.count++;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeItem(Item item) {
|
||||
final Class<? extends Item> klass = item.getClass();
|
||||
TypeInfo info = mTypes.get(klass);
|
||||
|
||||
if (info != null) {
|
||||
info.count--;
|
||||
if (info.count == 0) {
|
||||
// TODO cyril: Creating a pool to keep all TypeInfo instances
|
||||
// could be a great idea in the future.
|
||||
mTypes.remove(klass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context associated with this array adapter. The context is
|
||||
* used to create views from the resource passed to the constructor.
|
||||
*
|
||||
* @return The Context associated to this ItemAdapter
|
||||
*/
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of different views types used in this
|
||||
* ItemAdapter. Having a <em>getCurrentViewTypeCount</em> equal to
|
||||
* <em>getViewTypeCount</em> means you won't be able to add a new type of
|
||||
* view in this adapter (The Adapter class doesn't allow variable view type
|
||||
* count).
|
||||
*
|
||||
* @return The current number of different view types
|
||||
*/
|
||||
public int getActualViewTypeCount() {
|
||||
return mTypes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified object at the end of the array.
|
||||
*
|
||||
* @param object The object to add at the end of the array.
|
||||
*/
|
||||
public void add(Item item) {
|
||||
mItems.add(item);
|
||||
addItem(item);
|
||||
if (mNotifyOnChange) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified object at the specified index in the array.
|
||||
*
|
||||
* @param item The object to insert into the array.
|
||||
* @param index The index at which the object must be inserted.
|
||||
*/
|
||||
public void insert(Item item, int index) {
|
||||
mItems.add(index, item);
|
||||
addItem(item);
|
||||
if (mNotifyOnChange) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified object from the array.
|
||||
*
|
||||
* @param object The object to remove.
|
||||
*/
|
||||
public void remove(Item item) {
|
||||
if (mItems.remove(item)) {
|
||||
removeItem(item);
|
||||
if (mNotifyOnChange) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements from the list.
|
||||
*/
|
||||
public void clear() {
|
||||
mItems.clear();
|
||||
mTypes.clear();
|
||||
if (mNotifyOnChange) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the content of this adapter using the specified comparator.
|
||||
*
|
||||
* @param comparator The comparator used to sort the objects contained in
|
||||
* this adapter.
|
||||
*/
|
||||
public void sort(Comparator<? super Item> comparator) {
|
||||
Collections.sort(mItems, comparator);
|
||||
if (mNotifyOnChange) {
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Control whether methods that change the list ({@link #add},
|
||||
* {@link #insert}, {@link #remove}, {@link #clear}) automatically call
|
||||
* {@link #notifyDataSetChanged}. If set to false, caller must manually call
|
||||
* notifyDataSetChanged() to have the changes reflected in the attached
|
||||
* view. The default is true, and calling notifyDataSetChanged() resets the
|
||||
* flag to true.
|
||||
*
|
||||
* @param notifyOnChange if true, modifications to the list will
|
||||
* automatically call {@link #notifyDataSetChanged}
|
||||
*/
|
||||
public void setNotifyOnChange(boolean notifyOnChange) {
|
||||
mNotifyOnChange = notifyOnChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ItemAdapter from a given resource ID
|
||||
*
|
||||
* @param context The Context in which the ItemAdapter will be used in
|
||||
* @param xmlId The resource ID of an XML file that describes a set of
|
||||
* {@link Item}
|
||||
* @return a new ItemAdapter constructed with the content of the file
|
||||
* pointed by <em>xmlId</em>
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ItemAdapter createFromXml(Context context, int xmlId) throws XmlPullParserException, IOException {
|
||||
return createFromXml(context, context.getResources().getXml(xmlId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ItemAdapter from a given XML document. Called on a parser
|
||||
* positioned at a tag in an XML document, tries to create an ItemAdapter
|
||||
* from that tag.
|
||||
*
|
||||
* @param context The Context in which the ItemAdapter will be used in
|
||||
* @param xmlId The resource ID of an XML file that describes a set of
|
||||
* {@link Item}
|
||||
* @return a new ItemAdapter constructed with the content of the file
|
||||
* pointed by <em>xmlId</em>
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ItemAdapter createFromXml(Context context, XmlPullParser parser) throws XmlPullParserException,
|
||||
IOException {
|
||||
AttributeSet attrs = Xml.asAttributeSet(parser);
|
||||
|
||||
int type;
|
||||
while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) {
|
||||
// Empty loop
|
||||
}
|
||||
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
throw new XmlPullParserException("No start tag found");
|
||||
}
|
||||
|
||||
if (!parser.getName().equals("item-array")) {
|
||||
throw new XmlPullParserException("Unknown start tag. Should be 'item-array'");
|
||||
}
|
||||
|
||||
final List<Item> items = new ArrayList<Item>();
|
||||
final int innerDepth = parser.getDepth() + 1;
|
||||
final Resources r = context.getResources();
|
||||
|
||||
int depth;
|
||||
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||
&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
|
||||
if (type != XmlPullParser.START_TAG) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (depth > innerDepth) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = parser.getName();
|
||||
Item item;
|
||||
if (name.equals("text-item")) {
|
||||
item = new TextItem();
|
||||
} else if (name.equals("longtext-item")) {
|
||||
item = new LongTextItem();
|
||||
} else if (name.equals("description-item")) {
|
||||
item = new DescriptionItem();
|
||||
} else if (name.equals("separator-item")) {
|
||||
item = new SeparatorItem();
|
||||
} else if (name.equals("progress-item")) {
|
||||
item = new ProgressItem();
|
||||
} else if (name.equals("drawable-item")) {
|
||||
item = new DrawableItem();
|
||||
} else if (name.equals("subtitle-item")) {
|
||||
item = new SubtitleItem();
|
||||
} else if (name.equals("subtext-item")) {
|
||||
item = new SubtextItem();
|
||||
} else if (name.equals("thumbnail-item")) {
|
||||
item = new ThumbnailItem();
|
||||
} else {
|
||||
// TODO cyril: Remove that so that we can extend from
|
||||
// ItemAdapter and creates our own items via XML?
|
||||
throw new XmlPullParserException(parser.getPositionDescription() + ": invalid item tag " + name);
|
||||
}
|
||||
|
||||
// TODO cyril: Here we should call a method that children may
|
||||
// override to be able to create our own Items
|
||||
|
||||
if (item != null) {
|
||||
item.inflate(r, parser, attrs);
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return new ItemAdapter(context, items);
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return mItems.size();
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
return mItems.get(position);
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return mTypes.get(getItem(position).getClass()).type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return ((Item) getItem(position)).enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getViewTypeCount() {
|
||||
return mMaxViewTypeCount;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
|
||||
final Item item = (Item) getItem(position);
|
||||
ItemView cell = (ItemView) convertView;
|
||||
|
||||
if (cell == null) {
|
||||
cell = item.newView(mContext, null);
|
||||
cell.prepareItemView();
|
||||
}
|
||||
|
||||
cell.setObject(item);
|
||||
|
||||
return (View) cell;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* An extension of a {@link NormalActionBarItem} that supports a loading states.
|
||||
* When in loading state, a {@link LoaderActionBarItem} display an indeterminate
|
||||
* circular {@link ProgressBar}. This item is very handful with application
|
||||
* fetching data from the network or performing long background tasks.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class LoaderActionBarItem extends NormalActionBarItem {
|
||||
|
||||
private boolean mLoading;
|
||||
private View mButton;
|
||||
private View mProgressBar;
|
||||
|
||||
public LoaderActionBarItem() {
|
||||
mLoading = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View createItemView() {
|
||||
return LayoutInflater.from(mContext).inflate(R.layout.gd_action_bar_item_loader, mActionBar, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareItemView() {
|
||||
super.prepareItemView();
|
||||
mButton = mItemView.findViewById(R.id.gd_action_bar_item);
|
||||
mProgressBar = mItemView.findViewById(R.id.gd_action_bar_item_progress_bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onItemClicked() {
|
||||
super.onItemClicked();
|
||||
setLoading(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the loading state of this {@link LoaderActionBarItem}.
|
||||
*
|
||||
* @param loading The new loading state. If true, an indeterminate
|
||||
* {@link ProgressBar} is displayed. When false (default value)
|
||||
* the {@link ActionBarItem} behaves exactly like a regular
|
||||
* {@link NormalActionBarItem}.
|
||||
*/
|
||||
public void setLoading(boolean loading) {
|
||||
if (loading != mLoading) {
|
||||
mProgressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||
mButton.setVisibility(loading ? View.GONE : View.VISIBLE);
|
||||
mLoading = loading;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Default implementation of an {@link ActionBarItem}. A
|
||||
* {@link NormalActionBarItem} is a simple {@link ActionBarItem} containing a
|
||||
* single icon.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class NormalActionBarItem extends ActionBarItem {
|
||||
|
||||
@Override
|
||||
protected View createItemView() {
|
||||
return LayoutInflater.from(mContext).inflate(R.layout.gd_action_bar_item_base, mActionBar, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareItemView() {
|
||||
super.prepareItemView();
|
||||
final ImageButton imageButton = (ImageButton) mItemView.findViewById(R.id.gd_action_bar_item);
|
||||
imageButton.setImageDrawable(mDrawable);
|
||||
imageButton.setContentDescription(mContentDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContentDescriptionChanged() {
|
||||
super.onContentDescriptionChanged();
|
||||
mItemView.findViewById(R.id.gd_action_bar_item).setContentDescription(mContentDescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDrawableChanged() {
|
||||
super.onDrawableChanged();
|
||||
ImageButton imageButton = (ImageButton) mItemView.findViewById(R.id.gd_action_bar_item);
|
||||
imageButton.setImageDrawable(mDrawable);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* A QuickAction implements an item in a {@link QuickActionWidget}. A
|
||||
* QuickAction represents a single action and may contain a text and an icon.
|
||||
*
|
||||
* @author Benjamin Fellous
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class QuickAction {
|
||||
|
||||
public Drawable mDrawable;
|
||||
public CharSequence mTitle;
|
||||
|
||||
/* package */WeakReference<View> mView;
|
||||
|
||||
public QuickAction(Drawable d, CharSequence title) {
|
||||
mDrawable = d;
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
public QuickAction(Context ctx, int drawableId, CharSequence title) {
|
||||
mDrawable = ctx.getResources().getDrawable(drawableId);
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
public QuickAction(Context ctx, Drawable d, int titleId) {
|
||||
mDrawable = d;
|
||||
mTitle = ctx.getResources().getString(titleId);
|
||||
}
|
||||
|
||||
public QuickAction(Context ctx, int drawableId, int titleId) {
|
||||
mDrawable = ctx.getResources().getDrawable(drawableId);
|
||||
mTitle = ctx.getResources().getString(titleId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.MeasureSpec;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A QuickActionBar displays a set of {@link QuickAction} on a single row. In
|
||||
* case too many items are added to the QuickActionBar, the user can
|
||||
* horizontally scroll QuickActions. Using a QuickActionBar is a great
|
||||
* replacement for the long click UI pattern. For instance,
|
||||
* {@link QuickActionBar} adds secondary actions to an item of a
|
||||
* {@link ListView}.
|
||||
*
|
||||
* @author Benjamin Fellous
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class QuickActionBar extends QuickActionWidget {
|
||||
|
||||
private HorizontalScrollView mScrollView;
|
||||
private Animation mRackAnimation;
|
||||
private ViewGroup mRack;
|
||||
private ViewGroup mQuickActionItems;
|
||||
|
||||
private List<QuickAction> mQuickActions;
|
||||
|
||||
public QuickActionBar(Context context) {
|
||||
super(context);
|
||||
|
||||
mRackAnimation = AnimationUtils.loadAnimation(context, R.anim.gd_rack);
|
||||
|
||||
mRackAnimation.setInterpolator(new Interpolator() {
|
||||
public float getInterpolation(float t) {
|
||||
final float inner = (t * 1.55f) - 1.1f;
|
||||
return 1.2f - inner * inner;
|
||||
}
|
||||
});
|
||||
|
||||
setContentView(R.layout.gd_quick_action_bar);
|
||||
|
||||
final View v = getContentView();
|
||||
mRack = (ViewGroup) v.findViewById(R.id.gdi_rack);
|
||||
mQuickActionItems = (ViewGroup) v.findViewById(R.id.gdi_quick_action_items);
|
||||
mScrollView = (HorizontalScrollView) v.findViewById(R.id.gdi_scroll);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(View anchor) {
|
||||
super.show(anchor);
|
||||
mScrollView.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasureAndLayout(Rect anchorRect, View contentView) {
|
||||
|
||||
contentView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
int rootHeight = contentView.getMeasuredHeight();
|
||||
|
||||
int offsetY = getArrowOffsetY();
|
||||
int dyTop = anchorRect.top;
|
||||
int dyBottom = getScreenHeight() - anchorRect.bottom;
|
||||
|
||||
boolean onTop = (dyTop > dyBottom);
|
||||
int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY;
|
||||
|
||||
setWidgetSpecs(popupY, onTop);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateQuickActions(List<QuickAction> quickActions) {
|
||||
|
||||
mQuickActions = quickActions;
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
for (QuickAction action : quickActions) {
|
||||
TextView view = (TextView) inflater.inflate(R.layout.gd_quick_action_bar_item, mQuickActionItems, false);
|
||||
view.setText(action.mTitle);
|
||||
|
||||
view.setCompoundDrawablesWithIntrinsicBounds(null, action.mDrawable, null, null);
|
||||
view.setOnClickListener(mClickHandlerInternal);
|
||||
mQuickActionItems.addView(view);
|
||||
action.mView = new WeakReference<View>(view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClearQuickActions() {
|
||||
super.onClearQuickActions();
|
||||
mQuickActionItems.removeAllViews();
|
||||
}
|
||||
|
||||
private OnClickListener mClickHandlerInternal = new OnClickListener() {
|
||||
|
||||
public void onClick(View view) {
|
||||
|
||||
final OnQuickActionClickListener listener = getOnQuickActionClickListener();
|
||||
|
||||
if (listener != null) {
|
||||
final int itemCount = mQuickActions.size();
|
||||
for (int i = 0; i < itemCount; i++) {
|
||||
if (view == mQuickActions.get(i).mView.get()) {
|
||||
listener.onQuickActionClicked(QuickActionBar.this, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getDismissOnClick()) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.MeasureSpec;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.GridView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A {@link QuickActionGrid} is an implementation of a {@link QuickActionWidget}
|
||||
* that displays {@link QuickAction}s in a grid manner. This is usually used to create
|
||||
* a shortcut to jump between different type of information on screen.
|
||||
*
|
||||
* @author Benjamin Fellous
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class QuickActionGrid extends QuickActionWidget {
|
||||
|
||||
private GridView mGridView;
|
||||
|
||||
public QuickActionGrid(Context context) {
|
||||
super(context);
|
||||
|
||||
setContentView(R.layout.gd_quick_action_grid);
|
||||
|
||||
final View v = getContentView();
|
||||
mGridView = (GridView) v.findViewById(R.id.gdi_grid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void populateQuickActions(final List<QuickAction> quickActions) {
|
||||
|
||||
mGridView.setAdapter(new BaseAdapter() {
|
||||
|
||||
public View getView(int position, View view, ViewGroup parent) {
|
||||
|
||||
TextView textView = (TextView) view;
|
||||
|
||||
if (view == null) {
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
textView = (TextView) inflater.inflate(R.layout.gd_quick_action_grid_item, mGridView, false);
|
||||
}
|
||||
|
||||
QuickAction quickAction = quickActions.get(position);
|
||||
textView.setText(quickAction.mTitle);
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(null, quickAction.mDrawable, null, null);
|
||||
|
||||
return textView;
|
||||
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return quickActions.size();
|
||||
}
|
||||
});
|
||||
|
||||
mGridView.setOnItemClickListener(mInternalItemClickListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasureAndLayout(Rect anchorRect, View contentView) {
|
||||
|
||||
contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
|
||||
contentView.measure(MeasureSpec.makeMeasureSpec(getScreenWidth(), MeasureSpec.EXACTLY),
|
||||
LayoutParams.WRAP_CONTENT);
|
||||
|
||||
int rootHeight = contentView.getMeasuredHeight();
|
||||
|
||||
int offsetY = getArrowOffsetY();
|
||||
int dyTop = anchorRect.top;
|
||||
int dyBottom = getScreenHeight() - anchorRect.bottom;
|
||||
|
||||
boolean onTop = (dyTop > dyBottom);
|
||||
int popupY = (onTop) ? anchorRect.top - rootHeight + offsetY : anchorRect.bottom - offsetY;
|
||||
|
||||
setWidgetSpecs(popupY, onTop);
|
||||
}
|
||||
|
||||
private OnItemClickListener mInternalItemClickListener = new OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
||||
getOnQuickActionClickListener().onQuickActionClicked(QuickActionGrid.this, position);
|
||||
if (getDismissOnClick()) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -1,326 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.PopupWindow;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Abstraction of a {@link QuickAction} wrapper. A QuickActionWidget is
|
||||
* displayed on top of the user interface (it overlaps all UI elements but the
|
||||
* notification bar). Clients may listen to user actions using a
|
||||
* {@link OnQuickActionClickListener} .
|
||||
*
|
||||
* @author Benjamin Fellous
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public abstract class QuickActionWidget extends PopupWindow {
|
||||
|
||||
private static final int MEASURE_AND_LAYOUT_DONE = 1 << 1;
|
||||
|
||||
private final int[] mLocation = new int[2];
|
||||
protected final Rect mRect = new Rect();
|
||||
|
||||
private int mPrivateFlags;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private boolean mDismissOnClick;
|
||||
private int mArrowOffsetY;
|
||||
|
||||
private int mPopupY;
|
||||
private boolean mIsOnTop;
|
||||
|
||||
private int mScreenHeight;
|
||||
private int mScreenWidth;
|
||||
private boolean mIsDirty;
|
||||
|
||||
private OnQuickActionClickListener mOnQuickActionClickListener;
|
||||
private ArrayList<QuickAction> mQuickActions = new ArrayList<QuickAction>();
|
||||
|
||||
/**
|
||||
* Interface that may be used to listen to clicks on quick actions.
|
||||
*
|
||||
* @author Benjamin Fellous
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public static interface OnQuickActionClickListener {
|
||||
/**
|
||||
* Clients may implement this method to be notified of a click on a
|
||||
* particular quick action.
|
||||
*
|
||||
* @param position Position of the quick action that have been clicked.
|
||||
*/
|
||||
void onQuickActionClicked(QuickActionWidget widget, int position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new QuickActionWidget for the given context.
|
||||
*
|
||||
* @param context The context in which the QuickActionWidget is running in
|
||||
*/
|
||||
public QuickActionWidget(Context context) {
|
||||
super(context);
|
||||
|
||||
mContext = context;
|
||||
|
||||
initializeDefault();
|
||||
|
||||
setFocusable(true);
|
||||
setTouchable(true);
|
||||
setOutsideTouchable(true);
|
||||
setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
final WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
|
||||
mScreenWidth = windowManager.getDefaultDisplay().getWidth();
|
||||
mScreenHeight = windowManager.getDefaultDisplay().getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to {@link PopupWindow#setContentView(View)} but with a layout
|
||||
* identifier.
|
||||
*
|
||||
* @param layoutId The layout identifier of the view to use.
|
||||
*/
|
||||
public void setContentView(int layoutId) {
|
||||
setContentView(LayoutInflater.from(mContext).inflate(layoutId, null));
|
||||
}
|
||||
|
||||
private void initializeDefault() {
|
||||
mDismissOnClick = true;
|
||||
mArrowOffsetY = mContext.getResources().getDimensionPixelSize(R.dimen.gd_arrow_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the arrow offset for the Y axis.
|
||||
*
|
||||
* @see {@link #setArrowOffsetY(int)}
|
||||
* @return The arrow offset.
|
||||
*/
|
||||
public int getArrowOffsetY() {
|
||||
return mArrowOffsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the arrow offset to a new value. Setting an arrow offset may be
|
||||
* particular useful to warn which view the QuickActionWidget is related to.
|
||||
* By setting a positive offset, the arrow will overlap the view given by
|
||||
* {@link #show(View)}. The default value is 5dp.
|
||||
*
|
||||
* @param offsetY The offset for the Y axis
|
||||
*/
|
||||
public void setArrowOffsetY(int offsetY) {
|
||||
mArrowOffsetY = offsetY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the screen.
|
||||
*
|
||||
* @return The width of the screen
|
||||
*/
|
||||
protected int getScreenWidth() {
|
||||
return mScreenWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the screen.
|
||||
*
|
||||
* @return The height of the screen
|
||||
*/
|
||||
protected int getScreenHeight() {
|
||||
return mScreenHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, a {@link QuickActionWidget} is dismissed once the user
|
||||
* clicked on a {@link QuickAction}. This behavior can be changed using this
|
||||
* method.
|
||||
*
|
||||
* @param dismissOnClick True if you want the {@link QuickActionWidget} to
|
||||
* be dismissed on click else false.
|
||||
*/
|
||||
public void setDismissOnClick(boolean dismissOnClick) {
|
||||
mDismissOnClick = dismissOnClick;
|
||||
}
|
||||
|
||||
public boolean getDismissOnClick() {
|
||||
return mDismissOnClick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listener
|
||||
*/
|
||||
public void setOnQuickActionClickListener(OnQuickActionClickListener listener) {
|
||||
mOnQuickActionClickListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new QuickAction to this {@link QuickActionWidget}. Adding a new
|
||||
* {@link QuickAction} while the {@link QuickActionWidget} is currently
|
||||
* being shown does nothing. The new {@link QuickAction} will be displayed
|
||||
* on the next call to {@link #show(View)}.
|
||||
*
|
||||
* @param action The new {@link QuickAction} to add
|
||||
*/
|
||||
public void addQuickAction(QuickAction action) {
|
||||
if (action != null) {
|
||||
mQuickActions.add(action);
|
||||
mIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all {@link QuickAction} from this {@link QuickActionWidget}.
|
||||
*/
|
||||
public void clearAllQuickActions() {
|
||||
if (!mQuickActions.isEmpty()) {
|
||||
mQuickActions.clear();
|
||||
mIsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call that method to display the {@link QuickActionWidget} anchored to the
|
||||
* given view.
|
||||
*
|
||||
* @param anchor The view the {@link QuickActionWidget} will be anchored to.
|
||||
*/
|
||||
public void show(View anchor) {
|
||||
|
||||
final View contentView = getContentView();
|
||||
|
||||
if (contentView == null) {
|
||||
throw new IllegalStateException("You need to set the content view using the setContentView method");
|
||||
}
|
||||
|
||||
// Replaces the background of the popup with a cleared background
|
||||
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
final int[] loc = mLocation;
|
||||
anchor.getLocationOnScreen(loc);
|
||||
mRect.set(loc[0], loc[1], loc[0] + anchor.getWidth(), loc[1] + anchor.getHeight());
|
||||
|
||||
if (mIsDirty) {
|
||||
clearQuickActions();
|
||||
populateQuickActions(mQuickActions);
|
||||
}
|
||||
|
||||
onMeasureAndLayout(mRect, contentView);
|
||||
|
||||
if ((mPrivateFlags & MEASURE_AND_LAYOUT_DONE) != MEASURE_AND_LAYOUT_DONE) {
|
||||
throw new IllegalStateException("onMeasureAndLayout() did not set the widget specification by calling"
|
||||
+ " setWidgetSpecs()");
|
||||
}
|
||||
|
||||
showArrow();
|
||||
prepareAnimationStyle();
|
||||
|
||||
try {
|
||||
showAtLocation(anchor, Gravity.NO_GRAVITY, getShowAtX(), mPopupY);
|
||||
} catch (Exception e) {
|
||||
Log.w("quick-action-show", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected int getShowAtX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void clearQuickActions() {
|
||||
if (!mQuickActions.isEmpty()) {
|
||||
onClearQuickActions();
|
||||
}
|
||||
}
|
||||
|
||||
protected void onClearQuickActions() {
|
||||
}
|
||||
|
||||
protected abstract void populateQuickActions(List<QuickAction> quickActions);
|
||||
|
||||
protected abstract void onMeasureAndLayout(Rect anchorRect, View contentView);
|
||||
|
||||
protected void setWidgetSpecs(int popupY, boolean isOnTop) {
|
||||
mPopupY = popupY;
|
||||
mIsOnTop = isOnTop;
|
||||
|
||||
mPrivateFlags |= MEASURE_AND_LAYOUT_DONE;
|
||||
}
|
||||
|
||||
private void showArrow() {
|
||||
|
||||
final View contentView = getContentView();
|
||||
final int arrowId = mIsOnTop ? R.id.gdi_arrow_down : R.id.gdi_arrow_up;
|
||||
final View arrow = contentView.findViewById(arrowId);
|
||||
final View arrowUp = contentView.findViewById(R.id.gdi_arrow_up);
|
||||
final View arrowDown = contentView.findViewById(R.id.gdi_arrow_down);
|
||||
|
||||
if (arrowId == R.id.gdi_arrow_up) {
|
||||
arrowUp.setVisibility(View.VISIBLE);
|
||||
arrowDown.setVisibility(View.INVISIBLE);
|
||||
} else if (arrowId == R.id.gdi_arrow_down) {
|
||||
arrowUp.setVisibility(View.INVISIBLE);
|
||||
arrowDown.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams) arrow.getLayoutParams();
|
||||
param.leftMargin = getArrowLeftMargin(arrow);
|
||||
}
|
||||
|
||||
protected int getArrowLeftMargin(View arrow) {
|
||||
return mRect.centerX() - (arrow.getMeasuredWidth()) / 2;
|
||||
}
|
||||
|
||||
private void prepareAnimationStyle() {
|
||||
|
||||
final int screenWidth = mScreenWidth;
|
||||
final boolean onTop = mIsOnTop;
|
||||
final int arrowPointX = mRect.centerX();
|
||||
|
||||
if (arrowPointX <= screenWidth / 4) {
|
||||
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Left
|
||||
: R.style.GreenDroid_Animation_PopDown_Left);
|
||||
} else if (arrowPointX >= 3 * screenWidth / 4) {
|
||||
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Right
|
||||
: R.style.GreenDroid_Animation_PopDown_Right);
|
||||
} else {
|
||||
setAnimationStyle(onTop ? R.style.GreenDroid_Animation_PopUp_Center
|
||||
: R.style.GreenDroid_Animation_PopDown_Center);
|
||||
}
|
||||
}
|
||||
|
||||
protected Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
protected OnQuickActionClickListener getOnQuickActionClickListener() {
|
||||
return mOnQuickActionClickListener;
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import android.database.DataSetObservable;
|
||||
import android.database.DataSetObserver;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A SegmentedAdapter is a data source of a SegmentedHost/SegmentedHost.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public abstract class SegmentedAdapter {
|
||||
|
||||
private final DataSetObservable mDataSetObservable = new DataSetObservable();
|
||||
|
||||
/**
|
||||
* How many segments have to be displayed
|
||||
*
|
||||
* @return The number of segment displayed by the underlying SegmentedBar
|
||||
*/
|
||||
public abstract int getCount();
|
||||
|
||||
/**
|
||||
* Get the View associated to the segment at position <em>position</em>
|
||||
*
|
||||
* @param position The position of the item in the SegmentedAdapter
|
||||
* @param parent The parent that this view will eventually be attached to
|
||||
* @return A View corresponding to the segment at the given position
|
||||
*/
|
||||
public abstract View getView(int position, ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Get the title for the segment at position <em>position</em>
|
||||
*
|
||||
* @param position The position of the segment in the SegmentedBar
|
||||
* @return A title for the segment at the given position.
|
||||
*/
|
||||
public abstract String getSegmentTitle(int position);
|
||||
|
||||
/**
|
||||
* Register an observer that is called when changes happen to the data used
|
||||
* by this adapter.
|
||||
*
|
||||
* @param observer The object that gets notified when the data set changes.
|
||||
*/
|
||||
public void registerDataSetObserver(DataSetObserver observer) {
|
||||
mDataSetObservable.registerObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister an observer that has previously been registered with this
|
||||
* adapter via {@link #unregisterDataSetObserver(DataSetObserver)}
|
||||
*
|
||||
* @param observer The object to unregister
|
||||
*/
|
||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||
mDataSetObservable.unregisterObserver(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the attached View that the underlying data has changed and
|
||||
* should refresh itself.
|
||||
*/
|
||||
public void notifyDataSetChanged() {
|
||||
mDataSetObservable.notifyChanged();
|
||||
}
|
||||
}
|
||||
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A SegmentedBar displays a set of Buttons. Only one segment in a SegmentedBar
|
||||
* can be selected at a time. A SegmentedBar is very close to a TabWidget in
|
||||
* term of functionalities.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class SegmentedBar extends LinearLayout implements OnFocusChangeListener {
|
||||
|
||||
/**
|
||||
* Clients may use this listener to be notified of any changes that occurs
|
||||
* on the SegmentBar
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public static interface OnSegmentChangeListener {
|
||||
/**
|
||||
* Notification that the current segment has changed.
|
||||
*
|
||||
* @param index The index of the new selected segment.
|
||||
* @param clicked Whether the segment has been selected via a user
|
||||
* click.
|
||||
*/
|
||||
public void onSegmentChange(int index, boolean clicked);
|
||||
}
|
||||
|
||||
private OnSegmentChangeListener mOnSegmentChangeListener;
|
||||
private int mCheckedSegment;
|
||||
private Drawable mDividerDrawable;
|
||||
private int mDividerWidth;
|
||||
|
||||
public SegmentedBar(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SegmentedBar(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.gdSegmentedBarStyle);
|
||||
}
|
||||
|
||||
public SegmentedBar(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs);
|
||||
initSegmentedBar();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentedBar, defStyle, 0);
|
||||
|
||||
mDividerDrawable = a.getDrawable(R.styleable.SegmentedBar_dividerDrawable);
|
||||
mDividerWidth = a.getDimensionPixelSize(R.styleable.SegmentedBar_dividerWidth, 0);
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void initSegmentedBar() {
|
||||
mCheckedSegment = 0;
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
// Register ourselves so that we can handle focus on internal segments
|
||||
setFocusable(true);
|
||||
setOnFocusChangeListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the drawable that is used as divider between each segment.
|
||||
*
|
||||
* @param dividerDrawable The drawable to used as a divider. Note : using a
|
||||
* ColorDrawable will not work properly as the intrinsic width of
|
||||
* a ColorDrawable is -1.
|
||||
*/
|
||||
public void setDividerDrawable(Drawable dividerDrawable) {
|
||||
mDividerDrawable = dividerDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the drawable that is used as divider between each segment.
|
||||
*
|
||||
* @param resId The identifier of the Drawable to use.
|
||||
*/
|
||||
public void setDividerDrawable(int resId) {
|
||||
mDividerDrawable = getContext().getResources().getDrawable(resId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the divider that will be used as segment divider. If
|
||||
* the dividerWidth has not been set, the intrinsic width of the divider
|
||||
* drawable is used.
|
||||
*
|
||||
* @param width Width of the divider
|
||||
*/
|
||||
public void setDividerWidth(int width) {
|
||||
mDividerWidth = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of segment in this SegmentBar
|
||||
*
|
||||
* @return The number of segments in this SegmentBar
|
||||
*/
|
||||
public int getSegmentCount() {
|
||||
int segmentCount = getChildCount();
|
||||
// If we have divider we'll have an odd number of child
|
||||
if (mDividerDrawable != null) {
|
||||
segmentCount = (segmentCount + 1) / 2;
|
||||
}
|
||||
return segmentCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to register an OnSegmentChangeListener and listen to
|
||||
* changes that occur on this SegmentBar
|
||||
*
|
||||
* @param listener The listener to use
|
||||
*/
|
||||
public void setOnSegmentChangeListener(OnSegmentChangeListener listener) {
|
||||
mOnSegmentChangeListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current segment to the index <em>index</em>
|
||||
*
|
||||
* @param index The index of the segment to set. Client will be notified
|
||||
* using this method of the segment change.
|
||||
*/
|
||||
public void setCurrentSegment(int index) {
|
||||
if (index < 0 || index >= getSegmentCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
((CheckBox) getChildSegmentAt(mCheckedSegment)).setChecked(false);
|
||||
mCheckedSegment = index;
|
||||
((CheckBox) getChildSegmentAt(mCheckedSegment)).setChecked(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view representing the segment at the index <em>index</em>
|
||||
*
|
||||
* @param index The index of the segment to retrieve
|
||||
* @return The view that represents the segment at index <em>index</em>
|
||||
*/
|
||||
public View getChildSegmentAt(int index) {
|
||||
/*
|
||||
* If we are using dividers, then instead of segments at 0, 1, 2, ... we
|
||||
* have segments at 0, 2, 4, ...
|
||||
*/
|
||||
if (mDividerDrawable != null) {
|
||||
index *= 2;
|
||||
}
|
||||
return getChildAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a segment to the SegmentBar. This method automatically adds a
|
||||
* divider if needed.
|
||||
*
|
||||
* @param title The title of the segment to add.
|
||||
*/
|
||||
public void addSegment(String title) {
|
||||
|
||||
final Context context = getContext();
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
|
||||
/*
|
||||
* First of all, we have to check whether or not we need to add a
|
||||
* divider. A divider is added when there is at least one segment
|
||||
*/
|
||||
if (mDividerDrawable != null && getSegmentCount() > 0) {
|
||||
ImageView divider = new ImageView(context);
|
||||
final int width = (mDividerWidth > 0) ? mDividerWidth : mDividerDrawable.getIntrinsicWidth();
|
||||
final LinearLayout.LayoutParams lp = new LayoutParams(width, LayoutParams.FILL_PARENT);
|
||||
lp.setMargins(0, 0, 0, 0);
|
||||
divider.setLayoutParams(lp);
|
||||
divider.setBackgroundDrawable(mDividerDrawable);
|
||||
addView(divider);
|
||||
}
|
||||
|
||||
CheckBox segment = (CheckBox) inflater.inflate(R.layout.gd_segment, this, false);
|
||||
segment.setText(title);
|
||||
|
||||
segment.setClickable(true);
|
||||
segment.setFocusable(true);
|
||||
segment.setOnFocusChangeListener(this);
|
||||
segment.setOnCheckedChangeListener(new SegmentCheckedListener(getSegmentCount()));
|
||||
segment.setOnClickListener(new SegmentClickedListener(getSegmentCount()));
|
||||
|
||||
addView(segment);
|
||||
}
|
||||
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
|
||||
if (!hasFocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == this) {
|
||||
final View segment = getChildSegmentAt(mCheckedSegment);
|
||||
if (segment != null) {
|
||||
segment.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
final int segmentCounts = getSegmentCount();
|
||||
for (int i = 0; i < segmentCounts; i++) {
|
||||
if (getChildSegmentAt(i) == v) {
|
||||
setCurrentSegment(i);
|
||||
notifyListener(i, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SegmentClickedListener implements OnClickListener {
|
||||
|
||||
private final int mSegmentIndex;
|
||||
|
||||
private SegmentClickedListener(int segmentIndex) {
|
||||
mSegmentIndex = segmentIndex;
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
final CheckBox segment = (CheckBox) getChildSegmentAt(mCheckedSegment);
|
||||
if (mSegmentIndex == mCheckedSegment && !segment.isChecked()) {
|
||||
segment.setChecked(true);
|
||||
} else {
|
||||
notifyListener(mSegmentIndex, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SegmentCheckedListener implements OnCheckedChangeListener {
|
||||
|
||||
private final int mSegmentIndex;
|
||||
|
||||
private SegmentCheckedListener(int segmentIndex) {
|
||||
mSegmentIndex = segmentIndex;
|
||||
}
|
||||
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isChecked) {
|
||||
setCurrentSegment(mSegmentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyListener(int index, boolean clicked) {
|
||||
if (mOnSegmentChangeListener != null) {
|
||||
mOnSegmentChangeListener.onSegmentChange(index, clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget;
|
||||
|
||||
import greendroid.util.Config;
|
||||
import greendroid.widget.SegmentedBar.OnSegmentChangeListener;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.DataSetObserver;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A SegmentedHost is a wrapper view that handle a SegmentedBar and a
|
||||
* FrameLayout that hold the content. Data (titles, and content Views) are
|
||||
* provided to the SegmentedHost via a {@link SegmentedAdapter}.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class SegmentedHost extends LinearLayout {
|
||||
|
||||
private final static String LOG_TAG = SegmentedHost.class.getSimpleName();
|
||||
|
||||
private int mSegmentedBarId;
|
||||
private SegmentedBar mSegmentedBar;
|
||||
private int mSegmentedHostId;
|
||||
private FrameLayout mContentView;
|
||||
private int mSelectedSegment;
|
||||
|
||||
private SegmentedAdapter mAdapter;
|
||||
private View[] mViews;
|
||||
private DataSetObserver mSegmentObserver = new DataSetObserver() {
|
||||
|
||||
public void onChanged() {
|
||||
setupSegmentedHost(mSelectedSegment);
|
||||
}
|
||||
|
||||
public void onInvalidated() {
|
||||
// Do nothing - method never called
|
||||
}
|
||||
};
|
||||
|
||||
public SegmentedHost(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SegmentedHost(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.gdSegmentedHostStyle);
|
||||
}
|
||||
|
||||
public SegmentedHost(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs);
|
||||
initSegmentedView();
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SegmentedHost, defStyle, 0);
|
||||
|
||||
mSegmentedBarId = a.getResourceId(R.styleable.SegmentedHost_segmentedBar, -1);
|
||||
if (mSegmentedBarId <= 0) {
|
||||
throw new IllegalArgumentException("The segmentedBar attribute is required and must refer "
|
||||
+ "to a valid child.");
|
||||
}
|
||||
|
||||
mSegmentedHostId = a.getResourceId(R.styleable.SegmentedHost_segmentedContentView, -1);
|
||||
if (mSegmentedHostId <= 0) {
|
||||
throw new IllegalArgumentException("The segmentedHost attribute is required and must refer "
|
||||
+ "to a valid child.");
|
||||
}
|
||||
}
|
||||
|
||||
private void initSegmentedView() {
|
||||
setOrientation(LinearLayout.VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mSegmentedBar = (SegmentedBar) findViewById(mSegmentedBarId);
|
||||
if (mSegmentedBar == null) {
|
||||
throw new IllegalArgumentException("The segmentedBar attribute must refer to an existing child.");
|
||||
}
|
||||
mSegmentedBar.setOnSegmentChangeListener(new SegmentSwitcher());
|
||||
|
||||
mContentView = (FrameLayout) findViewById(mSegmentedHostId);
|
||||
if (mContentView == null) {
|
||||
throw new IllegalArgumentException("The segmentedHost attribute must refer to an existing child.");
|
||||
} else if (!(mContentView instanceof FrameLayout)) {
|
||||
throw new RuntimeException("The segmentedHost attribute must refer to a FrameLayout");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public SegmentedBar getSegmentedBar() {
|
||||
return mSegmentedBar;
|
||||
}
|
||||
|
||||
public FrameLayout getContentView() {
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
public void setAdapter(SegmentedAdapter adapter) {
|
||||
|
||||
if (mAdapter != null) {
|
||||
mAdapter.unregisterDataSetObserver(mSegmentObserver);
|
||||
}
|
||||
mAdapter = adapter;
|
||||
|
||||
if (adapter != null) {
|
||||
mAdapter.registerDataSetObserver(mSegmentObserver);
|
||||
}
|
||||
setupSegmentedHost(0);
|
||||
}
|
||||
|
||||
private void setupSegmentedHost(int selectedSegment) {
|
||||
|
||||
if (Config.GD_INFO_LOGS_ENABLED) {
|
||||
Log.i(LOG_TAG, "Preparing the SegmentedHost with the segment " + selectedSegment);
|
||||
}
|
||||
|
||||
mSegmentedBar.removeAllViews();
|
||||
mContentView.removeAllViews();
|
||||
mViews = null;
|
||||
|
||||
if (mAdapter != null) {
|
||||
// Add all segments to the Segmentedbar
|
||||
final int count = mAdapter.getCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mSegmentedBar.addSegment(mAdapter.getSegmentTitle(i));
|
||||
}
|
||||
|
||||
if (selectedSegment < 0) {
|
||||
selectedSegment = 0;
|
||||
} else if (selectedSegment > count) {
|
||||
selectedSegment = count;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
// Prepare the SegmentBar
|
||||
mViews = new View[count];
|
||||
mSegmentedBar.setCurrentSegment(selectedSegment);
|
||||
|
||||
// And displays the first view
|
||||
setContentView(selectedSegment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SegmentSwitcher implements OnSegmentChangeListener {
|
||||
public void onSegmentChange(int index, boolean clicked) {
|
||||
setContentView(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void setContentView(int index) {
|
||||
mSelectedSegment = index;
|
||||
mContentView.removeAllViews();
|
||||
if (mViews[index] == null) {
|
||||
mViews[index] = mAdapter.getView(index, SegmentedHost.this);
|
||||
}
|
||||
mContentView.addView(mViews[index]);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A description item displays a text on several lines. The default
|
||||
* implementation makes it disabled.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class DescriptionItem extends TextItem {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public DescriptionItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DescriptionItem with the given description.
|
||||
*
|
||||
* @param description The description for the current item.
|
||||
*/
|
||||
public DescriptionItem(String description) {
|
||||
super(description);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_description_item_view, parent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A DrawableItem displays a single Drawable on the left of the item cell and a
|
||||
* description text on the right. A DrawableItem takes care of adapting itself
|
||||
* depending on the presence of its Drawable.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class DrawableItem extends TextItem {
|
||||
|
||||
/**
|
||||
* The resource identifier for the drawable.
|
||||
*/
|
||||
public int drawableId;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public DrawableItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new DrawableItem that has no Drawable and displays the given
|
||||
* text. Used as it, a DrawableItem is very similar to a TextItem
|
||||
*
|
||||
* @param text The text of this DrawableItem
|
||||
*/
|
||||
public DrawableItem(String text) {
|
||||
this(text, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new DrawableItem that has no Drawable and displays the given
|
||||
* text. Used as it, a DrawableItem is very similar to a TextItem
|
||||
*
|
||||
* @param text The text of this DrawableItem
|
||||
* @param drawableId The resource identifier of the Drawable
|
||||
*/
|
||||
public DrawableItem(String text, int drawableId) {
|
||||
super(text);
|
||||
this.drawableId = drawableId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_drawable_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.DrawableItem);
|
||||
drawableId = a.getResourceId(R.styleable.DrawableItem_drawable, 0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Base class for all items used in GreenDroid. An item represents a wrapper of
|
||||
* data. Each item contains at least all the information needed to display a
|
||||
* single row in a {@link ListView}.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public abstract class Item {
|
||||
|
||||
private SparseArray<Object> mTags;
|
||||
private Object mTag;
|
||||
|
||||
/**
|
||||
* Set to true when this item is enabled?
|
||||
*/
|
||||
public boolean enabled;
|
||||
|
||||
/**
|
||||
* Constructs a new item.
|
||||
*/
|
||||
public Item() {
|
||||
// By default, an item is enabled
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tag associated to that item.
|
||||
*
|
||||
* @return The tag associated to this item.
|
||||
*/
|
||||
public Object getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag associated with this item. A tag is often used to store
|
||||
* extra information.
|
||||
*
|
||||
* @param tag The tag associated to this item
|
||||
*/
|
||||
public void setTag(Object tag) {
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tag associated with this item and the specified key.
|
||||
*
|
||||
* @param key The key of the tag to retrieve
|
||||
* @return The tag associated to the key <em>key</em> or null if no tags are
|
||||
* associated to that key
|
||||
*/
|
||||
public Object getTag(int key) {
|
||||
return (mTags == null) ? null : mTags.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a tag associated with this item and a key. A tag is often used to
|
||||
* store extra information.
|
||||
*
|
||||
* @param key The key for the specified tag
|
||||
* @param tag A tag that will be associated to that item
|
||||
*/
|
||||
public void setTag(int key, Object tag) {
|
||||
if (mTags == null) {
|
||||
mTags = new SparseArray<Object>();
|
||||
}
|
||||
mTags.put(key, tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that is associated to the current item. The returned view
|
||||
* is normally capable of being a good recipient for all item's information.
|
||||
*
|
||||
* @param context The context in which the {@link ItemView} will be used
|
||||
* @param parent The parent view of that new view. It is usually the parent
|
||||
* ListView
|
||||
* @return A new allocated view for the current Item
|
||||
*/
|
||||
public abstract ItemView newView(Context context, ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Helper method to inflate a layout using a given Context and a layoutID.
|
||||
*
|
||||
* @param context The current context
|
||||
* @param layoutID The identifier of the layout to inflate
|
||||
* @return A newly inflated view
|
||||
*/
|
||||
protected static ItemView createCellFromXml(Context context, int layoutID, ViewGroup parent) {
|
||||
return (ItemView) LayoutInflater.from(context).inflate(layoutID, parent, false);
|
||||
}
|
||||
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.Item);
|
||||
enabled = a.getBoolean(R.styleable.Item_enabled, enabled);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A LongTextItem is very similar to a regular {@link TextItem}. The only
|
||||
* difference is it may display the text on several lines.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class LongTextItem extends TextItem {
|
||||
|
||||
public LongTextItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public LongTextItem(String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_long_text_item_view, parent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Progress indicator that displays a centered text with a circular progress bar
|
||||
* when something is in progress.@
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ProgressItem extends TextItem {
|
||||
|
||||
private static final boolean DEFAULT_IS_IN_PROGRESS = false;
|
||||
|
||||
/**
|
||||
* The state of this item. When set to true, a circular progress bar
|
||||
* indicates something is going on/being computed.
|
||||
*/
|
||||
public boolean isInProgress;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public ProgressItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ProgressItem with the given text. By default, the circular
|
||||
* progress bar is not visible ... which indicates nothing is currently in
|
||||
* progress.
|
||||
*
|
||||
* @param text The text for this item
|
||||
*/
|
||||
public ProgressItem(String text) {
|
||||
this(text, DEFAULT_IS_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a ProgressItem with the given text and state.
|
||||
*
|
||||
* @param text The text for this item
|
||||
* @param isInProgress The state for this item
|
||||
*/
|
||||
public ProgressItem(String text, boolean isInProgress) {
|
||||
super(text);
|
||||
this.isInProgress = isInProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_progress_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.ProgressItem);
|
||||
isInProgress = a.getBoolean(R.styleable.ProgressItem_isInProgress, DEFAULT_IS_IN_PROGRESS);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* Acts as a separator between important {@link ListView} sections. A separator
|
||||
* display a text on a single line.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class SeparatorItem extends TextItem {
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public SeparatorItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a SeparatorItem made of the given text
|
||||
*
|
||||
* @param text The text for this SeparatorItem
|
||||
*/
|
||||
public SeparatorItem(String text) {
|
||||
super(text);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_separator_item_view, parent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A SubtextItem is really similar to a SubtitleItem as it displays a two lines
|
||||
* of text. The only difference between those two items are the number of lines
|
||||
* occupied by the content. A SubtextItem may generally used to display a
|
||||
* description text. As a result, it is disabled by default
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class SubtextItem extends TextItem {
|
||||
|
||||
/**
|
||||
* The string that will be displayed above the title of the item (possibly
|
||||
* on several lines).
|
||||
*/
|
||||
public String subtext;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public SubtextItem() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public SubtextItem(String text) {
|
||||
this(text, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SubtextItem
|
||||
*
|
||||
* @param text The main text for this item
|
||||
* @param subtext The subtext
|
||||
*/
|
||||
public SubtextItem(String text, String subtext) {
|
||||
super(text);
|
||||
this.subtext = subtext;
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_subtext_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.SubtextItem);
|
||||
subtext = a.getString(R.styleable.SubtextItem_subtext);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* An Item that contains two Strings : a text and a subtitle. The representation
|
||||
* of this Item is a view containing two lines of text. Uf you want to be sure,
|
||||
* the subtitle can occupy more than a single line, please use a
|
||||
* {@link SubtextItem}
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class SubtitleItem extends TextItem {
|
||||
|
||||
/**
|
||||
* The subtitle of this item
|
||||
*/
|
||||
public String subtitle;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public SubtitleItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SubtitleItem with the specified text and subtitle.
|
||||
*
|
||||
* @param text The text for this item
|
||||
* @param subtitle The item's subtitle
|
||||
*/
|
||||
public SubtitleItem(String text, String subtitle) {
|
||||
super(text);
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_subtitle_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.SubtitleItem);
|
||||
subtitle = a.getString(R.styleable.SubtitleItem_gdsubtitle);
|
||||
a.recycle();
|
||||
}
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A TextItem is a very basic item that only contains a single text. This text
|
||||
* will be displayed on a single line onto the screen.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class TextItem extends Item {
|
||||
|
||||
/**
|
||||
* The item's text.
|
||||
*/
|
||||
public String text;
|
||||
|
||||
public TextItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new TextItem with the specified text.
|
||||
*
|
||||
* @param text The text used to create this item.
|
||||
*/
|
||||
public TextItem(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_text_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.TextItem);
|
||||
text = a.getString(R.styleable.TextItem_text);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.item;
|
||||
|
||||
import greendroid.widget.itemview.ItemView;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
/**
|
||||
* A ThumbnailItem item is a complex item that wraps a drawable and two strings
|
||||
* : a title and a subtitle. The representation of that item is quite common to
|
||||
* Android users: The drawable is on the left of the item view and on the right
|
||||
* the title and the subtitle are displayed like a {@link SubtitleItem}.
|
||||
*
|
||||
* @author Cyril Mottier
|
||||
*/
|
||||
public class ThumbnailItem extends SubtitleItem {
|
||||
|
||||
/**
|
||||
* The resource ID for the drawable.
|
||||
*/
|
||||
public int drawableId;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public ThumbnailItem() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text
|
||||
* @param subtitle
|
||||
* @param drawableId
|
||||
*/
|
||||
public ThumbnailItem(String text, String subtitle, int drawableId) {
|
||||
super(text, subtitle);
|
||||
this.drawableId = drawableId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemView newView(Context context, ViewGroup parent) {
|
||||
return createCellFromXml(context, R.layout.gd_thumbnail_item_view, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException,
|
||||
IOException {
|
||||
super.inflate(r, parser, attrs);
|
||||
|
||||
TypedArray a = r.obtainAttributes(attrs, R.styleable.ThumbnailItem);
|
||||
drawableId = a.getResourceId(R.styleable.ThumbnailItem_thumbnail, drawableId);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.TextItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class DescriptionItemView extends TextView implements ItemView {
|
||||
|
||||
public DescriptionItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DescriptionItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public DescriptionItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
}
|
||||
|
||||
public void setObject(Item item) {
|
||||
setText(((TextItem) item).text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.DrawableItem;
|
||||
import greendroid.widget.item.Item;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class DrawableItemView extends LinearLayout implements ItemView {
|
||||
|
||||
private TextView mTextView;
|
||||
private ImageView mImageView;
|
||||
|
||||
public DrawableItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DrawableItemView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
mTextView = (TextView) findViewById(R.id.gd_text);
|
||||
mImageView = (ImageView) findViewById(R.id.gd_drawable);
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final DrawableItem item = (DrawableItem) object;
|
||||
mTextView.setText(item.text);
|
||||
|
||||
final int drawableId = item.drawableId;
|
||||
if (drawableId == 0) {
|
||||
mImageView.setVisibility(View.GONE);
|
||||
} else {
|
||||
mImageView.setVisibility(View.VISIBLE);
|
||||
mImageView.setImageResource(drawableId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
|
||||
public interface ItemView {
|
||||
|
||||
void prepareItemView();
|
||||
|
||||
void setObject(Item item);
|
||||
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.LongTextItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class LongTextItemView extends TextView implements ItemView {
|
||||
|
||||
public LongTextItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public LongTextItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public LongTextItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
}
|
||||
|
||||
public void setObject(Item item) {
|
||||
setText(((LongTextItem) item).text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.ProgressItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class ProgressItemView extends FrameLayout implements ItemView {
|
||||
|
||||
private ProgressBar mProgressBar;
|
||||
private TextView mTextView;
|
||||
|
||||
public ProgressItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ProgressItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ProgressItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
mProgressBar = (ProgressBar) findViewById(R.id.gd_progress_bar);
|
||||
mTextView = (TextView) findViewById(R.id.gd_text);
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final ProgressItem item = (ProgressItem) object;
|
||||
mProgressBar.setVisibility(item.isInProgress ? View.VISIBLE : View.GONE);
|
||||
mTextView.setText(item.text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.TextItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class SeparatorItemView extends TextView implements ItemView {
|
||||
|
||||
public SeparatorItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SeparatorItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SeparatorItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final TextItem item = (TextItem) object;
|
||||
setText(item.text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.SubtextItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class SubtextItemView extends LinearLayout implements ItemView {
|
||||
|
||||
private TextView mTextView;
|
||||
private TextView mSubtextView;
|
||||
|
||||
public SubtextItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SubtextItemView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
mTextView = (TextView) findViewById(R.id.gd_text);
|
||||
mSubtextView = (TextView) findViewById(R.id.gd_subtext);
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final SubtextItem item = (SubtextItem) object;
|
||||
mTextView.setText(item.text);
|
||||
mSubtextView.setText(item.subtext);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.SubtitleItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class SubtitleItemView extends LinearLayout implements ItemView {
|
||||
|
||||
private TextView mTextView;
|
||||
private TextView mSubtitleView;
|
||||
|
||||
public SubtitleItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SubtitleItemView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
mTextView = (TextView) findViewById(R.id.gd_text);
|
||||
mSubtitleView = (TextView) findViewById(R.id.gd_subtitle);
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final SubtitleItem item = (SubtitleItem) object;
|
||||
mTextView.setText(item.text);
|
||||
mSubtitleView.setText(item.subtitle);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.TextItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class TextItemView extends TextView implements ItemView {
|
||||
|
||||
public TextItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TextItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TextItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
setText(((TextItem) object).text);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
*
|
||||
* 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 greendroid.widget.itemview;
|
||||
|
||||
import greendroid.widget.item.Item;
|
||||
import greendroid.widget.item.ThumbnailItem;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.cyrilmottier.android.greendroid.R;
|
||||
|
||||
public class ThumbnailItemView extends RelativeLayout implements ItemView {
|
||||
|
||||
private TextView mTextView;
|
||||
private TextView mSubtitleView;
|
||||
private ImageView mThumbnailView;
|
||||
|
||||
public ThumbnailItemView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ThumbnailItemView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public ThumbnailItemView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void prepareItemView() {
|
||||
mTextView = (TextView) findViewById(R.id.gd_text);
|
||||
mSubtitleView = (TextView) findViewById(R.id.gd_subtitle);
|
||||
mThumbnailView = (ImageView) findViewById(R.id.gd_thumbnail);
|
||||
}
|
||||
|
||||
public void setObject(Item object) {
|
||||
final ThumbnailItem item = (ThumbnailItem) object;
|
||||
mTextView.setText(item.text);
|
||||
mSubtitleView.setText(item.subtitle);
|
||||
mThumbnailView.setImageResource(item.drawableId);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="100%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="0%"
|
||||
android:pivotY="50%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="100%"
|
||||
android:pivotY="50%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="0%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="0.3"
|
||||
android:toXScale="1.0"
|
||||
android:fromYScale="0.3"
|
||||
android:toYScale="1.0"
|
||||
android:pivotX="100%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/decelerate_interpolator"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<translate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0"
|
||||
android:duration="325" />
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="100%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="0%"
|
||||
android:pivotY="0%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="100%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="100%"
|
||||
android:pivotY="100%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright (C) 2010 Cyril Mottier (http://www.cyrilmottier.com)
|
||||
**
|
||||
** 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<scale
|
||||
android:fromXScale="1.0"
|
||||
android:toXScale="0.3"
|
||||
android:fromYScale="1.0"
|
||||
android:toYScale="0.3"
|
||||
android:pivotX="0%"
|
||||
android:pivotY="100%"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
<alpha
|
||||
android:interpolator="@android:anim/accelerate_interpolator"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
|
||||
</set>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 491 B |
|
Before Width: | Height: | Size: 340 B |
|
Before Width: | Height: | Size: 461 B |
|
Before Width: | Height: | Size: 575 B |
|
Before Width: | Height: | Size: 425 B |
|
Before Width: | Height: | Size: 479 B |
|
Before Width: | Height: | Size: 253 B |
|
Before Width: | Height: | Size: 258 B |
|
Before Width: | Height: | Size: 246 B |
|
Before Width: | Height: | Size: 591 B |