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 |