Merge branch 'develop' into cancel_transfer_for_deleted_users

This commit is contained in:
masensio 2015-02-03 11:25:09 +01:00
commit b64fd4cc5b
48 changed files with 1684 additions and 371 deletions

View file

@ -1,4 +1,4 @@
#Mon Jan 19 09:42:11 CET 2015
#Sun Jan 18 17:01:43 CET 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 476 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
res/drawable-xhdpi/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -32,7 +32,7 @@
android:orientation="horizontal" >
<ImageView
android:id="@+id/imageView1"
android:id="@+id/thumbnail"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"

View file

@ -35,7 +35,7 @@
android:padding="8dp" >
<ImageView
android:id="@+id/imageView1"
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"

86
res/layout/grid_image.xml Normal file
View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
ownCloud Android client application
Copyright (C) 2014 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ListItemLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="@drawable/list_selector"
android:gravity="center_horizontal"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<com.owncloud.android.ui.SquareImageView
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:scaleType="centerCrop"
android:src="@drawable/ic_menu_archive"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:orientation="vertical"
android:layout_margin="4dp">
<ImageView
android:id="@+id/sharedIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="4dp"
android:src="@drawable/sharedlink" />
<ImageView
android:id="@+id/sharedWithMeIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="4dp"
android:src="@drawable/shared_with_me"
android:visibility="invisible" />
</LinearLayout>
<ImageView
android:id="@+id/localFileIndicator"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="bottom|right"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
android:src="@drawable/local_file_indicator" />
<ImageView
android:id="@+id/favoriteIcon"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
android:src="@drawable/ic_favorite" />
</FrameLayout>
</LinearLayout>

102
res/layout/grid_item.xml Normal file
View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
ownCloud Android client application
Copyright (C) 2014 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<com.owncloud.android.ui.SquareLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ListItemLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="@drawable/list_selector"
android:gravity="center"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" >
<ImageView
android:id="@+id/thumbnail"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_gravity="center_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:src="@drawable/ic_menu_archive" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:orientation="vertical"
android:layout_margin="2dp">
<ImageView
android:id="@+id/sharedIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="2dp"
android:src="@drawable/sharedlink" />
<ImageView
android:id="@+id/sharedWithMeIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="2dp"
android:src="@drawable/shared_with_me"
android:visibility="invisible" />
</LinearLayout>
<ImageView
android:id="@+id/localFileIndicator"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="bottom|right"
android:layout_marginTop="2dp"
android:layout_marginRight="2dp"
android:src="@drawable/local_file_indicator" />
<ImageView
android:id="@+id/favoriteIcon"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="2dp"
android:layout_marginRight="2dp"
android:src="@drawable/ic_favorite" />
</FrameLayout>
<TextView
android:id="@+id/Filename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:ellipsize="middle"
android:gravity="center_horizontal"
android:singleLine="true"
android:text="TextView"
android:textColor="@color/textColor"
android:textSize="16dip" />
</com.owncloud.android.ui.SquareLinearLayout>

View file

@ -3,7 +3,7 @@
ownCloud Android client application
Copyright (C) 2012 Bartek Przybylski
Copyright (C) 2012-2013 ownCloud Inc.
Copyright (C) 2012-2015 ownCloud Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2,
@ -16,11 +16,12 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_files"
@ -29,32 +30,36 @@
android:layout_weight="1"
android:footerDividersEnabled="false" >
<com.owncloud.android.ui.ExtendedListView
<third_parties.in.srain.cube.GridViewWithHeaderAndFooter
android:id="@+id/list_root"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
android:columnWidth="100dp"
android:gravity="center"
android:horizontalSpacing="2dp"
android:stretchMode="columnWidth"
android:verticalSpacing="2dp"
android:visibility="visible" />
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.v4.widget.SwipeRefreshLayout
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_files_emptyView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/empty_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:text="@string/empty"
android:layout_gravity="center"
android:visibility="visible" />
</ScrollView>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/empty_list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical|center_horizontal"
android:text="@string/empty"
android:visibility="visible" />
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>

View file

@ -19,129 +19,141 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ListItemLayout"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:background="@drawable/list_selector"
android:orientation="horizontal"
android:orientation="vertical"
android:layout_height="56dp">
<FrameLayout
android:layout_width="56dp"
android:layout_height="56dp"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="@+id/imageView2"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginLeft="22dp"
android:src="@drawable/local_file_indicator" />
<ImageView
android:id="@+id/imageView1"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginLeft="9dp"
android:src="@drawable/ic_menu_archive" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="10dp"
android:layout_marginRight="2dp"
android:src="@drawable/ic_favorite" />
</FrameLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical" >
android:orientation="horizontal">
<TextView
android:id="@+id/Filename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:ellipsize="middle"
android:singleLine="true"
android:text="TextView"
android:textColor="#303030"
android:textSize="16dip" />
<FrameLayout
android:layout_width="56dp"
android:layout_height="56dp"
android:focusable="false"
android:focusableInTouchMode="false">
<ImageView
android:id="@+id/localFileIndicator"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginLeft="22dp"
android:src="@drawable/local_file_indicator" />
<ImageView
android:id="@+id/thumbnail"
android:layout_width="@dimen/file_icon_size"
android:layout_height="@dimen/file_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginLeft="9dp"
android:src="@drawable/ic_menu_archive" />
<ImageView
android:id="@+id/favoriteIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="10dp"
android:layout_marginRight="2dp"
android:src="@drawable/ic_favorite" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:weightSum="1">
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical" >
<TextView
android:id="@+id/last_mod"
android:id="@+id/Filename"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:ellipsize="middle"
android:singleLine="true"
android:text="TextView"
android:layout_weight=".5"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:textSize="12dip"/>
android:textColor="#303030"
android:textSize="16dip" />
<TextView
android:id="@+id/file_size"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="TextView"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:layout_weight=".5"
android:textSize="12dip"/>
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:weightSum="1">
<TextView
android:id="@+id/last_mod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_weight=".5"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:textSize="12dip"/>
<TextView
android:id="@+id/file_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="TextView"
android:textColor="@color/list_item_lastmod_and_filesize_text"
android:layout_weight=".5"
android:textSize="12dip"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="25dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<ImageView
android:id="@+id/sharedIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
android:src="@drawable/sharedlink" />
<ImageView
android:id="@+id/sharedWithMeIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="4dp"
android:src="@drawable/shared_with_me"
android:visibility="invisible" />
</LinearLayout>
<ImageView
android:id="@+id/custom_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:gravity=""
android:src="@android:drawable/checkbox_off_background" />
</LinearLayout>
<LinearLayout
android:layout_width="25dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<ImageView
android:id="@+id/sharedIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
android:src="@drawable/sharedlink" />
<ImageView
android:id="@+id/sharedWithMeIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginTop="4dp"
android:src="@drawable/shared_with_me" />
</LinearLayout>
<ImageView
android:id="@+id/custom_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:gravity=""
android:src="@android:drawable/checkbox_off_background" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/list_divider_background"></View>
</LinearLayout>

View file

@ -30,7 +30,7 @@
android:layout_gravity="center_vertical|center"
android:layout_margin="4dp"
android:src="@drawable/ic_menu_archive"
android:id="@+id/imageView1" />
android:id="@+id/thumbnail" />
<TextView
android:text="TextView"

View file

@ -22,5 +22,7 @@
<color name="filelist_icon_backgorund">#DDDDDD</color>
<color name="owncloud_blue_bright">#00ddff</color>
<color name="list_item_lastmod_and_filesize_text">#989898</color>
<color name="textColor">#303030</color>
<color name="list_divider_background">#fff0f0f0</color>
</resources>

View file

@ -18,4 +18,5 @@
-->
<resources>
<dimen name="file_icon_size">32dp</dimen>
<dimen name="file_icon_size_grid">128dp</dimen>
</resources>

View file

@ -243,7 +243,7 @@ public class ThumbnailsCacheManager {
private int getThumbnailDimension(){
// Converts dp to pixel
Resources r = MainApp.getAppContext().getResources();
return (int) Math.round(r.getDimension(R.dimen.file_icon_size));
return (int) Math.round(r.getDimension(R.dimen.file_icon_size_grid));
}
private Bitmap doOCFileInBackground() {

View file

@ -1,73 +0,0 @@
/* ownCloud Android client application
* Copyright (C) 2012 Bartek Przybylski
* Copyright (C) 2012-2013 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* ListView allowing to specify the position of an item that should be centered in the visible area, if possible.
*
* The cleanest way I found to overcome the problem due to getHeight() returns 0 until the view is really drawn.
*
* @author David A. Velasco
*/
public class ExtendedListView extends ListView {
private int mPositionToSetAndCenter;
public ExtendedListView(Context context) {
super(context);
}
public ExtendedListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExtendedListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* {@inheritDoc}
*
*
*/
@Override
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
if (mPositionToSetAndCenter > 0) {
this.setSelectionFromTop(mPositionToSetAndCenter, getHeight() / 2);
mPositionToSetAndCenter = 0;
}
}
/**
* Public method to set the position of the item that should be centered in the visible area of the view.
*
* The position is saved here and checked in onDraw().
*
* @param position Position (in the list of items) of the item to center in the visible area.
*/
public void setAndCenterSelection(int position) {
mPositionToSetAndCenter = position;
}
}

View file

@ -0,0 +1,42 @@
/* ownCloud Android client application
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
public class SquareImageView extends ImageView {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}

View file

@ -0,0 +1,42 @@
/* ownCloud Android client application
* Copyright (C) 2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.owncloud.android.ui;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
public class SquareLinearLayout extends LinearLayout {
public SquareLinearLayout(Context context) {
super(context);
}
public SquareLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}

View file

@ -1,6 +1,6 @@
/* ownCloud Android client application
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2012-2014 ownCloud Inc.
* Copyright (C) 2012-2015 ownCloud Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@ -31,9 +31,9 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.owncloud.android.R;
@ -63,12 +63,15 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
private Context mContext;
private OCFile mFile = null;
private Vector<OCFile> mFiles = null;
private Vector<OCFile> mFilesOrig = new Vector<OCFile>();
private boolean mJustFolders;
private FileDataStorageManager mStorageManager;
private Account mAccount;
private ComponentsGetter mTransferServiceGetter;
private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };
private SharedPreferences mAppPreferences;
public FileListListAdapter(
@ -80,7 +83,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
mJustFolders = justFolders;
mContext = context;
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
mTransferServiceGetter = transferServiceGetter;
mAppPreferences = PreferenceManager
@ -93,7 +95,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
// initialise thumbnails cache on background thread
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
}
@Override
@ -132,90 +133,158 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
boolean fileView = DisplayUtils.decideViewLayout(mFiles);
View view = convertView;
if (view == null) {
LayoutInflater inflator = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflator.inflate(R.layout.list_item, null);
}
OCFile file = null;
LayoutInflater inflator = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (mFiles != null && mFiles.size() > position) {
OCFile file = mFiles.get(position);
TextView fileName = (TextView) view.findViewById(R.id.Filename);
String name = file.getFileName();
file = mFiles.get(position);
}
fileName.setText(name);
ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);
// Find out which layout should be displayed
ViewType viewType;
if (!fileView){
viewType = ViewType.LIST_ITEM;
} else if (file.isImage()){
viewType = ViewType.GRID_IMAGE;
} else {
viewType = ViewType.GRID_ITEM;
}
// Create View
switch (viewType){
case GRID_IMAGE:
view = inflator.inflate(R.layout.grid_image, null);
break;
case GRID_ITEM:
view = inflator.inflate(R.layout.grid_item, null);
break;
case LIST_ITEM:
view = inflator.inflate(R.layout.list_item, null);
break;
}
view.invalidate();
if (file != null){
ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);
fileIcon.setTag(file.getFileId());
ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);
ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);
sharedWithMeIconV.setVisibility(View.GONE);
TextView fileName;
String name;
ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);
localStateView.bringToFront();
FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();
FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();
boolean downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file));
OperationsServiceBinder opsBinder = mTransferServiceGetter.getOperationsServiceBinder();
downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, file.getRemotePath()));
if (downloading) {
localStateView.setImageResource(R.drawable.downloading_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {
localStateView.setImageResource(R.drawable.uploading_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else if (file.isDown()) {
localStateView.setImageResource(R.drawable.local_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else {
localStateView.setVisibility(View.INVISIBLE);
switch (viewType){
case LIST_ITEM:
TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);
lastModV.setVisibility(View.VISIBLE);
lastModV.setText(showRelativeTimestamp(file));
checkBoxV.setVisibility(View.GONE);
fileSizeV.setVisibility(View.VISIBLE);
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
if (!file.isFolder()) {
GridView parentList = (GridView)parent;
if (parentList.getChoiceMode() == GridView.CHOICE_MODE_NONE) {
checkBoxV.setVisibility(View.GONE);
} else {
if (parentList.isItemChecked(position)) {
checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
} else {
checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
}
checkBoxV.setVisibility(View.VISIBLE);
}
} else { //Folder
fileSizeV.setVisibility(View.INVISIBLE);
}
case GRID_ITEM:
// filename
fileName = (TextView) view.findViewById(R.id.Filename);
name = file.getFileName();
fileName.setText(name);
case GRID_IMAGE:
// sharedIcon
ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);
if (file.isShareByLink()) {
sharedIconV.setVisibility(View.VISIBLE);
sharedIconV.bringToFront();
} else {
sharedIconV.setVisibility(View.GONE);
}
// local state
ImageView localStateView = (ImageView) view.findViewById(R.id.localFileIndicator);
localStateView.bringToFront();
FileDownloaderBinder downloaderBinder = mTransferServiceGetter.getFileDownloaderBinder();
FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();
boolean downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file));
OperationsServiceBinder opsBinder = mTransferServiceGetter.getOperationsServiceBinder();
downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, file.getRemotePath()));
if (downloading) {
localStateView.setImageResource(R.drawable.downloading_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {
localStateView.setImageResource(R.drawable.uploading_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else if (file.isDown()) {
localStateView.setImageResource(R.drawable.local_file_indicator);
localStateView.setVisibility(View.VISIBLE);
} else {
localStateView.setVisibility(View.INVISIBLE);
}
// share with me icon
if (!file.isFolder()) {
ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);
sharedWithMeIconV.bringToFront();
if (checkIfFileIsSharedWithMe(file)) {
sharedWithMeIconV.setVisibility(View.VISIBLE);
} else {
sharedWithMeIconV.setVisibility(View.GONE);
}
}
break;
}
TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);
// For all Views
// this if-else is needed even though favorite icon is visible by default
// because android reuses views in listview
if (!file.keepInSync()) {
view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);
} else {
view.findViewById(R.id.favoriteIcon).setVisibility(View.VISIBLE);
}
// No Folder
if (!file.isFolder()) {
fileSizeV.setVisibility(View.VISIBLE);
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
lastModV.setVisibility(View.VISIBLE);
lastModV.setText(showRelativeTimestamp(file));
// this if-else is needed even thoe fav icon is visible by default
// because android reuses views in listview
if (!file.keepInSync()) {
view.findViewById(R.id.imageView3).setVisibility(View.GONE);
} else {
view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);
}
ListView parentList = (ListView)parent;
if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) {
checkBoxV.setVisibility(View.GONE);
} else {
if (parentList.isItemChecked(position)) {
checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
} else {
checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
}
checkBoxV.setVisibility(View.VISIBLE);
}
// get Thumbnail if file is image
if (file.isImage() && file.getRemoteId() != null){
// Thumbnail in Cache?
// Thumbnail in Cache?
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
String.valueOf(file.getRemoteId())
);
);
if (thumbnail != null && !file.needsUpdateThumbnail()){
fileIcon.setImageBitmap(thumbnail);
} else {
// generate new Thumbnail
if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(
fileIcon, mStorageManager, mAccount
);
);
if (thumbnail == null) {
thumbnail = ThumbnailsCacheManager.mDefaultImg;
}
@ -224,7 +293,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
mContext.getResources(),
thumbnail,
task
);
);
fileIcon.setImageDrawable(asyncDrawable);
task.execute(file);
}
@ -232,45 +301,19 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
} else {
fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName()));
}
if (checkIfFileIsSharedWithMe(file)) {
sharedWithMeIconV.setVisibility(View.VISIBLE);
}
}
else {
// TODO Re-enable when server supports folder-size calculation
// if (FileStorageUtils.getDefaultSavePathFor(mAccount.name, file) != null){
// fileSizeV.setVisibility(View.VISIBLE);
// fileSizeV.setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)));
// } else {
fileSizeV.setVisibility(View.INVISIBLE);
// }
lastModV.setVisibility(View.VISIBLE);
lastModV.setText(showRelativeTimestamp(file));
checkBoxV.setVisibility(View.GONE);
view.findViewById(R.id.imageView3).setVisibility(View.GONE);
} else {
// Folder
if (checkIfFileIsSharedWithMe(file)) {
fileIcon.setImageResource(R.drawable.shared_with_me_folder);
sharedWithMeIconV.setVisibility(View.VISIBLE);
} else if (file.isShareByLink()) {
// If folder is sharedByLink, icon folder must be changed to
// folder-public one
fileIcon.setImageResource(R.drawable.folder_public);
} else {
fileIcon.setImageResource(
DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())
);
}
// If folder is sharedByLink, icon folder must be changed to
// folder-public one
if (file.isShareByLink()) {
fileIcon.setImageResource(R.drawable.folder_public);
}
}
if (file.isShareByLink()) {
sharedIconV.setVisibility(View.VISIBLE);
} else {
sharedIconV.setVisibility(View.GONE);
}
}
@ -347,6 +390,9 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
}
if (mStorageManager != null) {
mFiles = mStorageManager.getFolderContent(mFile);
mFilesOrig.clear();
mFilesOrig.addAll(mFiles);
if (mJustFolders) {
mFiles = getFolders(mFiles);
}

View file

@ -37,6 +37,8 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
/**
* This Adapter populates a ListView with all files and directories contained
* in a local directory
@ -102,7 +104,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
String name = file.getName();
fileName.setText(name);
ImageView fileIcon = (ImageView) view.findViewById(R.id.imageView1);
ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);
if (!file.isDirectory()) {
fileIcon.setImageResource(R.drawable.file);
} else {
@ -116,9 +118,10 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
if (!file.isDirectory()) {
fileSizeV.setVisibility(View.VISIBLE);
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.length()));
lastModV.setVisibility(View.VISIBLE);
lastModV.setText(DisplayUtils.unixTimeToHumanReadable(file.lastModified()));
ListView parentList = (ListView)parent;
GridViewWithHeaderAndFooter parentList = (GridViewWithHeaderAndFooter)parent;
if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) {
checkBoxV.setVisibility(View.GONE);
} else {
@ -167,8 +170,9 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
checkBoxV.setVisibility(View.GONE);
}
view.findViewById(R.id.imageView2).setVisibility(View.INVISIBLE); // not GONE; the alignment would change
view.findViewById(R.id.imageView3).setVisibility(View.GONE);
// not GONE; the alignment changes; ugly way to keep it
view.findViewById(R.id.localFileIndicator).setVisibility(View.INVISIBLE);
view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);
view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);
view.findViewById(R.id.sharedWithMeIcon).setVisibility(View.GONE);

View file

@ -27,14 +27,14 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.ExtendedListView;
import third_parties.in.srain.cube.GridViewWithHeaderAndFooter;
import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
/**
@ -52,8 +52,6 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
private static final String KEY_HEIGHT_CELL = "HEIGHT_CELL";
private static final String KEY_EMPTY_LIST_MESSAGE = "EMPTY_LIST_MESSAGE";
protected ExtendedListView mList;
private SwipeRefreshLayout mRefreshLayout;
private SwipeRefreshLayout mRefreshEmptyLayout;
private TextView mEmptyListMessage;
@ -66,32 +64,51 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
private OnEnforceableRefreshListener mOnRefreshListener = null;
protected GridViewWithHeaderAndFooter imageView;
public void setListAdapter(ListAdapter listAdapter) {
mList.setAdapter(listAdapter);
mList.invalidate();
imageView.setAdapter(listAdapter);
imageView.invalidate();
}
public GridView getGridView() {
return imageView;
}
public void setFooterView(View footer) {
mList.addFooterView(footer, null, false);
mList.invalidate();
imageView.addFooterView(footer, null, false);
imageView.invalidate();
}
public ListView getListView() {
return mList;
public void removeFooterView(View footer) {
imageView.removeFooterView(footer);
imageView.invalidate();
}
public int getFooterViewCount() {
return imageView.getFooterViewCount();
}
protected void switchImageView(){
imageView.setNumColumns(GridView.AUTO_FIT);
imageView.invalidateRowHeight(); // Force to recalculate mRowHeight of imageView
imageView.invalidate();
}
protected void switchFileView(){
imageView.setNumColumns(1);
imageView.invalidate();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log_OC.e(TAG, "onCreateView");
View v = inflater.inflate(R.layout.list_fragment, null);
mEmptyListMessage = (TextView) v.findViewById(R.id.empty_list_view);
mList = (ExtendedListView) (v.findViewById(R.id.list_root));
mList.setOnItemClickListener(this);
mList.setDivider(getResources().getDrawable(R.drawable.uploader_list_separator));
mList.setDividerHeight(1);
imageView = (GridViewWithHeaderAndFooter)(v.findViewById(R.id.list_root));
imageView.setOnItemClickListener(this);
if (savedInstanceState != null) {
int referencePosition = savedInstanceState.getInt(KEY_SAVED_LIST_POSITION);
@ -101,11 +118,12 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
// Pull down refresh
mRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files);
mRefreshEmptyLayout = (SwipeRefreshLayout) v.findViewById(R.id.swipe_refresh_files_emptyView);
mEmptyListMessage = (TextView) v.findViewById(R.id.empty_list_view);
onCreateSwipeToRefresh(mRefreshLayout);
onCreateSwipeToRefresh(mRefreshEmptyLayout);
mList.setEmptyView(mRefreshEmptyLayout);
imageView.setEmptyView(mRefreshEmptyLayout);
return v;
}
@ -157,8 +175,8 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
* screen.
*/
protected int getReferencePosition() {
if (mList != null) {
return (mList.getFirstVisiblePosition() + mList.getLastVisiblePosition()) / 2;
if (imageView != null) {
return (imageView.getFirstVisiblePosition() + imageView.getLastVisiblePosition()) / 2;
} else {
return 0;
}
@ -171,8 +189,8 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
* {@link LocalFileListFragment#getReferencePosition()}
*/
protected void setReferencePosition(int position) {
if (mList != null) {
mList.setAndCenterSelection(position);
if (imageView != null) {
imageView.setSelection(position);
}
}
@ -190,22 +208,14 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
int top = mTops.remove(mTops.size() - 1);
mList.setSelectionFromTop(firstPosition, top);
imageView.smoothScrollToPosition(firstPosition);
// Move the scroll if the selection is not visible
int indexPosition = mHeightCell*index;
int height = mList.getHeight();
int height = imageView.getHeight();
if (indexPosition > height) {
if (android.os.Build.VERSION.SDK_INT >= 11)
{
mList.smoothScrollToPosition(index);
}
else if (android.os.Build.VERSION.SDK_INT >= 8)
{
mList.setSelectionFromTop(index, 0);
}
imageView.smoothScrollToPosition(index);
}
}
}
@ -217,10 +227,10 @@ implements OnItemClickListener, OnEnforceableRefreshListener {
mIndexes.add(index);
int firstPosition = mList.getFirstVisiblePosition();
int firstPosition = imageView.getFirstVisiblePosition();
mFirstPositions.add(firstPosition);
View view = mList.getChildAt(0);
View view = imageView.getChildAt(0);
int top = (view == null) ? 0 : view.getTop() ;
mTops.add(top);

View file

@ -76,7 +76,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log_OC.i(TAG, "onCreateView() start");
View v = super.onCreateView(inflater, container, savedInstanceState);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
getGridView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
disableSwipe(); // Disable pull refresh
setMessageForEmptyList(getString(R.string.local_file_list_empty));
Log_OC.i(TAG, "onCreateView() end");
@ -98,7 +98,6 @@ public class LocalFileListFragment extends ExtendedListFragment {
Log_OC.i(TAG, "onActivityCreated() stop");
}
/**
* Checks the file clicked over. Browses inside if it is a directory. Notifies the container activity in any case.
*/
@ -118,7 +117,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
} else { /// Click on a file
ImageView checkBoxV = (ImageView) v.findViewById(R.id.custom_checkbox);
if (checkBoxV != null) {
if (getListView().isItemChecked(position)) {
if (getGridView().isItemChecked(position)) {
checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
} else {
checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
@ -195,10 +194,10 @@ public class LocalFileListFragment extends ExtendedListFragment {
directory = directory.getParentFile();
}
mList.clearChoices(); // by now, only files in the same directory will be kept as selected
imageView.clearChoices(); // by now, only files in the same directory will be kept as selected
mAdapter.swapDirectory(directory);
if (mDirectory == null || !mDirectory.equals(directory)) {
mList.setSelectionFromTop(0, 0);
imageView.setSelection(0);
}
mDirectory = directory;
}
@ -211,11 +210,11 @@ public class LocalFileListFragment extends ExtendedListFragment {
*/
public String[] getCheckedFilePaths() {
ArrayList<String> result = new ArrayList<String>();
SparseBooleanArray positions = mList.getCheckedItemPositions();
SparseBooleanArray positions = imageView.getCheckedItemPositions();
if (positions.size() > 0) {
for (int i = 0; i < positions.size(); i++) {
if (positions.get(positions.keyAt(i)) == true) {
result.add(((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
result.add(((File) imageView.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
}
}

View file

@ -29,6 +29,7 @@ import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.TextView;
@ -48,6 +49,7 @@ import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.ui.preview.PreviewMediaFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileStorageUtils;
/**
@ -136,9 +138,9 @@ public class OCFileListFragment extends ExtendedListFragment {
);
setListAdapter(mAdapter);
registerForContextMenu(getListView());
getListView().setOnCreateContextMenuListener(this);
}
registerForContextMenu(getGridView());
getGridView().setOnCreateContextMenuListener(this);
}
/**
* Saves the current listed folder.
@ -389,15 +391,19 @@ public class OCFileListFragment extends ExtendedListFragment {
mAdapter.swapDirectory(directory, storageManager);
if (mFile == null || !mFile.equals(directory)) {
mList.setSelectionFromTop(0, 0);
imageView.setSelection(0);
}
mFile = directory;
Vector<OCFile> files = storageManager.getFolderContent(directory);
// Update Footer
TextView footerText = (TextView) mFooterView.findViewById(R.id.footerText);
Log_OC.d("footer", String.valueOf(System.currentTimeMillis()));
footerText.setText(generateFooterText(directory));
Log_OC.d("footer", String.valueOf(System.currentTimeMillis()));
if (DisplayUtils.decideViewLayout(files)){
switchImageView();
} else {
switchFileView();
}
}
}
@ -434,6 +440,17 @@ public class OCFileListFragment extends ExtendedListFragment {
output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folders);
}
// Fix for showing or not to show the footerView
if (folders == 0 && files == 0) { // If no files or folders, remove footerView for allowing
// to show the emptyList message
removeFooterView(mFooterView);
} else { // set a new footerView if there is not one for showing the number or files/folders
if (getFooterViewCount()== 0) {
((ViewGroup)mFooterView.getParent()).removeView(mFooterView);
setFooterView(mFooterView);
}
}
return output;
}

View file

@ -26,6 +26,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.Vector;
import android.annotation.TargetApi;
import android.content.Context;
@ -51,6 +52,8 @@ public class DisplayUtils {
private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
private final static Double THUMBNAIL_THRESHOLD = 0.5;
private static HashMap<String, String> mimeType2HUmanReadable;
static {
mimeType2HUmanReadable = new HashMap<String, String>();
@ -228,7 +231,7 @@ public class DisplayUtils {
/**
* Converts Unix time to human readable format
* @param miliseconds that have passed since 01/01/1970
* @param milliseconds that have passed since 01/01/1970
* @return The human readable time for the users locale
*/
public static String unixTimeToHumanReadable(long milliseconds) {
@ -340,4 +343,31 @@ public class DisplayUtils {
}
return path;
}
/**
*
* @param mFiles
* @return true: imageView, false: listView
*/
public static boolean decideViewLayout(Vector<OCFile> mFiles){
// decide image vs. file view
double countImages = 0;
double countFiles = 0;
for (OCFile file : mFiles){
if (!file.isFolder()){
countFiles++;
if (file.isImage()){
countImages++;
}
}
}
if ((countImages / countFiles) >= THUMBNAIL_THRESHOLD){
return true;
} else {
return false;
}
}
}

View file

@ -0,0 +1,787 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package third_parties.in.srain.cube;
import android.annotation.TargetApi;
import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
/**
* A {@link GridView} that supports adding header rows in a
* very similar way to {@link android.widget.ListView}.
* See {@link GridViewWithHeaderAndFooter#addHeaderView(View, Object, boolean)}
* See {@link GridViewWithHeaderAndFooter#addFooterView(View, Object, boolean)}
*/
public class GridViewWithHeaderAndFooter extends GridView {
public static boolean DEBUG = false;
/**
* A class that represents a fixed view in a list, for example a header at the top
* or a footer at the bottom.
*/
private static class FixedViewInfo {
/**
* The view to add to the grid
*/
public View view;
public ViewGroup viewContainer;
/**
* The data backing the view. This is returned from {@link ListAdapter#getItem(int)}.
*/
public Object data;
/**
* <code>true</code> if the fixed view should be selectable in the grid
*/
public boolean isSelectable;
}
private int mNumColumns = AUTO_FIT;
private View mViewForMeasureRowHeight = null;
private int mRowHeight = -1;
private static final String LOG_TAG = "grid-view-with-header-and-footer";
private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>();
private ArrayList<FixedViewInfo> mFooterViewInfos = new ArrayList<FixedViewInfo>();
private void initHeaderGridView() {
}
public GridViewWithHeaderAndFooter(Context context) {
super(context);
initHeaderGridView();
}
public GridViewWithHeaderAndFooter(Context context, AttributeSet attrs) {
super(context, attrs);
initHeaderGridView();
}
public GridViewWithHeaderAndFooter(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initHeaderGridView();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ListAdapter adapter = getAdapter();
if (adapter != null && adapter instanceof HeaderViewGridAdapter) {
((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumnsCompatible());
((HeaderViewGridAdapter) adapter).setRowHeight(getRowHeight());
}
}
@Override
public void setClipChildren(boolean clipChildren) {
// Ignore, since the header rows depend on not being clipped
}
/**
* Do not call this method unless you know how it works.
*
* @param clipChildren
*/
public void setClipChildrenSupper(boolean clipChildren) {
super.setClipChildren(false);
}
/**
* Add a fixed view to appear at the top of the grid. If addHeaderView is
* called more than once, the views will appear in the order they were
* added. Views added using this call can take focus if they want.
* <p/>
* NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
* the supplied cursor with one that will also account for header views.
*
* @param v The view to add.
*/
public void addHeaderView(View v) {
addHeaderView(v, null, true);
}
/**
* Add a fixed view to appear at the top of the grid. If addHeaderView is
* called more than once, the views will appear in the order they were
* added. Views added using this call can take focus if they want.
* <p/>
* NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap
* the supplied cursor with one that will also account for header views.
*
* @param v The view to add.
* @param data Data to associate with this view
* @param isSelectable whether the item is selectable
*/
public void addHeaderView(View v, Object data, boolean isSelectable) {
ListAdapter adapter = getAdapter();
if (adapter != null && !(adapter instanceof HeaderViewGridAdapter)) {
throw new IllegalStateException(
"Cannot add header view to grid -- setAdapter has already been called.");
}
ViewGroup.LayoutParams lyp = v.getLayoutParams();
FixedViewInfo info = new FixedViewInfo();
FrameLayout fl = new FullWidthFixedViewLayout(getContext());
if (lyp != null) {
v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
}
fl.addView(v);
info.view = v;
info.viewContainer = fl;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
// in the case of re-adding a header view, or adding one later on,
// we need to notify the observer
if (adapter != null) {
((HeaderViewGridAdapter) adapter).notifyDataSetChanged();
}
}
public void addFooterView(View v) {
addFooterView(v, null, true);
}
public void addFooterView(View v, Object data, boolean isSelectable) {
ListAdapter mAdapter = getAdapter();
if (mAdapter != null && !(mAdapter instanceof HeaderViewGridAdapter)) {
throw new IllegalStateException(
"Cannot add header view to grid -- setAdapter has already been called.");
}
ViewGroup.LayoutParams lyp = v.getLayoutParams();
FixedViewInfo info = new FixedViewInfo();
FrameLayout fl = new FullWidthFixedViewLayout(getContext());
if (lyp != null) {
v.setLayoutParams(new FrameLayout.LayoutParams(lyp.width, lyp.height));
fl.setLayoutParams(new AbsListView.LayoutParams(lyp.width, lyp.height));
}
fl.addView(v);
info.view = v;
info.viewContainer = fl;
info.data = data;
info.isSelectable = isSelectable;
mFooterViewInfos.add(info);
if (mAdapter != null) {
((HeaderViewGridAdapter) mAdapter).notifyDataSetChanged();
}
}
public int getHeaderViewCount() {
return mHeaderViewInfos.size();
}
public int getFooterViewCount() {
return mFooterViewInfos.size();
}
/**
* Removes a previously-added header view.
*
* @param v The view to remove
* @return true if the view was removed, false if the view was not a header
* view
*/
public boolean removeHeaderView(View v) {
if (mHeaderViewInfos.size() > 0) {
boolean result = false;
ListAdapter adapter = getAdapter();
if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) {
result = true;
}
removeFixedViewInfo(v, mHeaderViewInfos);
return result;
}
return false;
}
/**
* Removes a previously-added footer view.
*
* @param v The view to remove
* @return true if the view was removed, false if the view was not a header
* view
*/
public boolean removeFooterView(View v) {
if (mFooterViewInfos.size() > 0) {
boolean result = false;
ListAdapter adapter = getAdapter();
if (adapter != null && ((HeaderViewGridAdapter) adapter).removeFooter(v)) {
result = true;
}
removeFixedViewInfo(v, mFooterViewInfos);
return result;
}
return false;
}
private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) {
int len = where.size();
for (int i = 0; i < len; ++i) {
FixedViewInfo info = where.get(i);
if (info.view == v) {
where.remove(i);
break;
}
}
}
@TargetApi(11)
private int getNumColumnsCompatible() {
if (Build.VERSION.SDK_INT >= 11) {
return super.getNumColumns();
} else {
try {
Field numColumns = getClass().getSuperclass().getDeclaredField("mNumColumns");
numColumns.setAccessible(true);
return numColumns.getInt(this);
} catch (Exception e) {
if (mNumColumns != -1) {
return mNumColumns;
}
throw new RuntimeException("Can not determine the mNumColumns for this API platform, please call setNumColumns to set it.");
}
}
}
@TargetApi(16)
private int getColumnWidthCompatible() {
if (Build.VERSION.SDK_INT >= 16) {
return super.getColumnWidth();
} else {
try {
Field numColumns = getClass().getSuperclass().getDeclaredField("mColumnWidth");
numColumns.setAccessible(true);
return numColumns.getInt(this);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mViewForMeasureRowHeight = null;
}
public void invalidateRowHeight() {
mRowHeight = -1;
}
public int getRowHeight() {
if (mRowHeight > 0) {
return mRowHeight;
}
ListAdapter adapter = getAdapter();
int numColumns = getNumColumnsCompatible();
// adapter has not been set or has no views in it;
if (adapter == null || adapter.getCount() <= numColumns * (mHeaderViewInfos.size() + mFooterViewInfos.size())) {
return -1;
}
int mColumnWidth = getColumnWidthCompatible();
View view = getAdapter().getView(numColumns * mHeaderViewInfos.size(), mViewForMeasureRowHeight, this);
AbsListView.LayoutParams p = (AbsListView.LayoutParams) view.getLayoutParams();
if (p == null) {
p = new AbsListView.LayoutParams(-1, -2, 0);
view.setLayoutParams(p);
}
int childHeightSpec = getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
int childWidthSpec = getChildMeasureSpec(
MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
view.measure(childWidthSpec, childHeightSpec);
mViewForMeasureRowHeight = view;
mRowHeight = view.getMeasuredHeight();
return mRowHeight;
}
@TargetApi(11)
public void tryToScrollToBottomSmoothly() {
int lastPos = getAdapter().getCount() - 1;
if (Build.VERSION.SDK_INT >= 11) {
smoothScrollToPositionFromTop(lastPos, 0);
} else {
setSelection(lastPos);
}
}
@TargetApi(11)
public void tryToScrollToBottomSmoothly(int duration) {
int lastPos = getAdapter().getCount() - 1;
if (Build.VERSION.SDK_INT >= 11) {
smoothScrollToPositionFromTop(lastPos, 0, duration);
} else {
setSelection(lastPos);
}
}
@Override
public void setAdapter(ListAdapter adapter) {
if (mHeaderViewInfos.size() > 0 || mFooterViewInfos.size() > 0) {
HeaderViewGridAdapter headerViewGridAdapter = new HeaderViewGridAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
int numColumns = getNumColumnsCompatible();
if (numColumns > 1) {
headerViewGridAdapter.setNumColumns(numColumns);
}
headerViewGridAdapter.setRowHeight(getRowHeight());
super.setAdapter(headerViewGridAdapter);
} else {
super.setAdapter(adapter);
}
}
/**
* full width
*/
private class FullWidthFixedViewLayout extends FrameLayout {
public FullWidthFixedViewLayout(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int realLeft = GridViewWithHeaderAndFooter.this.getPaddingLeft() + getPaddingLeft();
// Try to make where it should be, from left, full width
if (realLeft != left) {
offsetLeftAndRight(realLeft - left);
}
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int targetWidth = GridViewWithHeaderAndFooter.this.getMeasuredWidth()
- GridViewWithHeaderAndFooter.this.getPaddingLeft()
- GridViewWithHeaderAndFooter.this.getPaddingRight();
widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth,
MeasureSpec.getMode(widthMeasureSpec));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
public void setNumColumns(int numColumns) {
super.setNumColumns(numColumns);
mNumColumns = numColumns;
ListAdapter adapter = getAdapter();
if (adapter != null && adapter instanceof HeaderViewGridAdapter) {
((HeaderViewGridAdapter) adapter).setNumColumns(numColumns);
}
}
/**
* ListAdapter used when a HeaderGridView has header views. This ListAdapter
* wraps another one and also keeps track of the header views and their
* associated data objects.
* <p>This is intended as a base class; you will probably not need to
* use this class directly in your own code.
*/
private static class HeaderViewGridAdapter implements WrapperListAdapter, Filterable {
// This is used to notify the container of updates relating to number of columns
// or headers changing, which changes the number of placeholders needed
private final DataSetObservable mDataSetObservable = new DataSetObservable();
private final ListAdapter mAdapter;
static final ArrayList<FixedViewInfo> EMPTY_INFO_LIST =
new ArrayList<FixedViewInfo>();
// This ArrayList is assumed to NOT be null.
ArrayList<FixedViewInfo> mHeaderViewInfos;
ArrayList<FixedViewInfo> mFooterViewInfos;
private int mNumColumns = 1;
private int mRowHeight = -1;
boolean mAreAllFixedViewsSelectable;
private final boolean mIsFilterable;
private boolean mCachePlaceHoldView = true;
// From Recycle Bin or calling getView, this a question...
private boolean mCacheFirstHeaderView = false;
public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ArrayList<FixedViewInfo> footViewInfos, ListAdapter adapter) {
mAdapter = adapter;
mIsFilterable = adapter instanceof Filterable;
if (headerViewInfos == null) {
mHeaderViewInfos = EMPTY_INFO_LIST;
} else {
mHeaderViewInfos = headerViewInfos;
}
if (footViewInfos == null) {
mFooterViewInfos = EMPTY_INFO_LIST;
} else {
mFooterViewInfos = footViewInfos;
}
mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos);
}
public void setNumColumns(int numColumns) {
if (numColumns < 1) {
return;
}
if (mNumColumns != numColumns) {
mNumColumns = numColumns;
notifyDataSetChanged();
}
}
public void setRowHeight(int height) {
mRowHeight = height;
}
public int getHeadersCount() {
return mHeaderViewInfos.size();
}
public int getFootersCount() {
return mFooterViewInfos.size();
}
@Override
public boolean isEmpty() {
return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0 && getFootersCount() == 0;
}
private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) {
if (infos != null) {
for (FixedViewInfo info : infos) {
if (!info.isSelectable) {
return false;
}
}
}
return true;
}
public boolean removeHeader(View v) {
for (int i = 0; i < mHeaderViewInfos.size(); i++) {
FixedViewInfo info = mHeaderViewInfos.get(i);
if (info.view == v) {
mHeaderViewInfos.remove(i);
mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos) && areAllListInfosSelectable(mFooterViewInfos);
mDataSetObservable.notifyChanged();
return true;
}
}
return false;
}
public boolean removeFooter(View v) {
for (int i = 0; i < mFooterViewInfos.size(); i++) {
FixedViewInfo info = mFooterViewInfos.get(i);
if (info.view == v) {
mFooterViewInfos.remove(i);
mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos) && areAllListInfosSelectable(mFooterViewInfos);
mDataSetObservable.notifyChanged();
return true;
}
}
return false;
}
@Override
public int getCount() {
if (mAdapter != null) {
return (getFootersCount() + getHeadersCount()) * mNumColumns + getAdapterAndPlaceHolderCount();
} else {
return (getFootersCount() + getHeadersCount()) * mNumColumns;
}
}
@Override
public boolean areAllItemsEnabled() {
if (mAdapter != null) {
return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
} else {
return true;
}
}
private int getAdapterAndPlaceHolderCount() {
final int adapterCount = (int) (Math.ceil(1f * mAdapter.getCount() / mNumColumns) * mNumColumns);
return adapterCount;
}
@Override
public boolean isEnabled(int position) {
// Header (negative positions will throw an IndexOutOfBoundsException)
int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
if (position < numHeadersAndPlaceholders) {
return position % mNumColumns == 0
&& mHeaderViewInfos.get(position / mNumColumns).isSelectable;
}
// Adapter
final int adjPosition = position - numHeadersAndPlaceholders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = getAdapterAndPlaceHolderCount();
if (adjPosition < adapterCount) {
return adjPosition < mAdapter.getCount() && mAdapter.isEnabled(adjPosition);
}
}
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
final int footerPosition = adjPosition - adapterCount;
return footerPosition % mNumColumns == 0
&& mFooterViewInfos.get(footerPosition / mNumColumns).isSelectable;
}
@Override
public Object getItem(int position) {
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
if (position < numHeadersAndPlaceholders) {
if (position % mNumColumns == 0) {
return mHeaderViewInfos.get(position / mNumColumns).data;
}
return null;
}
// Adapter
final int adjPosition = position - numHeadersAndPlaceholders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = getAdapterAndPlaceHolderCount();
if (adjPosition < adapterCount) {
if (adjPosition < mAdapter.getCount()) {
return mAdapter.getItem(adjPosition);
} else {
return null;
}
}
}
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
final int footerPosition = adjPosition - adapterCount;
if (footerPosition % mNumColumns == 0) {
return mFooterViewInfos.get(footerPosition).data;
} else {
return null;
}
}
@Override
public long getItemId(int position) {
int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
if (mAdapter != null && position >= numHeadersAndPlaceholders) {
int adjPosition = position - numHeadersAndPlaceholders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition);
}
}
return -1;
}
@Override
public boolean hasStableIds() {
if (mAdapter != null) {
return mAdapter.hasStableIds();
}
return false;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (DEBUG) {
Log.d(LOG_TAG, String.format("getView: %s, reused: %s", position, convertView == null));
}
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
if (position < numHeadersAndPlaceholders) {
View headerViewContainer = mHeaderViewInfos
.get(position / mNumColumns).viewContainer;
if (position % mNumColumns == 0) {
return headerViewContainer;
} else {
if (convertView == null) {
convertView = new View(parent.getContext());
}
// We need to do this because GridView uses the height of the last item
// in a row to determine the height for the entire row.
convertView.setVisibility(View.INVISIBLE);
convertView.setMinimumHeight(headerViewContainer.getHeight());
return convertView;
}
}
// Adapter
final int adjPosition = position - numHeadersAndPlaceholders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = getAdapterAndPlaceHolderCount();
if (adjPosition < adapterCount) {
if (adjPosition < mAdapter.getCount()) {
View view = mAdapter.getView(adjPosition, convertView, parent);
return view;
} else {
if (convertView == null) {
convertView = new View(parent.getContext());
}
convertView.setVisibility(View.INVISIBLE);
convertView.setMinimumHeight(mRowHeight);
return convertView;
}
}
}
// Footer
final int footerPosition = adjPosition - adapterCount;
if (footerPosition < getCount()) {
View footViewContainer = mFooterViewInfos
.get(footerPosition / mNumColumns).viewContainer;
if (position % mNumColumns == 0) {
return footViewContainer;
} else {
if (convertView == null) {
convertView = new View(parent.getContext());
}
// We need to do this because GridView uses the height of the last item
// in a row to determine the height for the entire row.
convertView.setVisibility(View.INVISIBLE);
convertView.setMinimumHeight(footViewContainer.getHeight());
return convertView;
}
}
throw new ArrayIndexOutOfBoundsException(position);
}
@Override
public int getItemViewType(int position) {
final int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns;
final int adapterViewTypeStart = mAdapter == null ? 0 : mAdapter.getViewTypeCount() - 1;
int type = AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
if (mCachePlaceHoldView) {
// Header
if (position < numHeadersAndPlaceholders) {
if (position == 0) {
if (mCacheFirstHeaderView) {
type = adapterViewTypeStart + mHeaderViewInfos.size() + mFooterViewInfos.size() + 1 + 1;
}
}
if (position % mNumColumns != 0) {
type = adapterViewTypeStart + (position / mNumColumns + 1);
}
}
}
// Adapter
final int adjPosition = position - numHeadersAndPlaceholders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = getAdapterAndPlaceHolderCount();
if (adjPosition >= 0 && adjPosition < adapterCount) {
if (adjPosition < mAdapter.getCount()) {
type = mAdapter.getItemViewType(adjPosition);
} else {
if (mCachePlaceHoldView) {
type = adapterViewTypeStart + mHeaderViewInfos.size() + 1;
}
}
}
}
if (mCachePlaceHoldView) {
// Footer
final int footerPosition = adjPosition - adapterCount;
if (footerPosition >= 0 && footerPosition < getCount() && (footerPosition % mNumColumns) != 0) {
type = adapterViewTypeStart + mHeaderViewInfos.size() + 1 + (footerPosition / mNumColumns + 1);
}
}
if (DEBUG) {
Log.d(LOG_TAG, String.format("getItemViewType: pos: %s, result: %s", position, type, mCachePlaceHoldView, mCacheFirstHeaderView));
}
return type;
}
/**
* content view, content view holder, header[0], header and footer placeholder(s)
*
* @return
*/
@Override
public int getViewTypeCount() {
int count = mAdapter == null ? 1 : mAdapter.getViewTypeCount();
if (mCachePlaceHoldView) {
int offset = mHeaderViewInfos.size() + 1 + mFooterViewInfos.size();
if (mCacheFirstHeaderView) {
offset += 1;
}
count += offset;
}
if (DEBUG) {
Log.d(LOG_TAG, String.format("getViewTypeCount: %s", count));
}
return count;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
if (mAdapter != null) {
mAdapter.registerDataSetObserver(observer);
}
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(observer);
}
}
@Override
public Filter getFilter() {
if (mIsFilterable) {
return ((Filterable) mAdapter).getFilter();
}
return null;
}
@Override
public ListAdapter getWrappedAdapter() {
return mAdapter;
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
}

View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.