添加列表缩略图模式
This commit is contained in:
1 parent
0ea49f593b
commit
5fda8b792c
31 files changed
+5682
-972
No files matched your search
@@ -26,7 +26,7 @@
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="8dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.HfListView
|
||||
<com.hippo.ehviewer.widget.PullListView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
File renamed without changes.
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 Hippo Seven
|
||||
<!--
|
||||
Copyright (C) 2014 Hippo Seven
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -12,24 +13,33 @@
|
||||
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.
|
||||
-->
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" >
|
||||
|
||||
|
||||
<com.hippo.ehviewer.widget.FswView
|
||||
android:id="@+id/alignment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true" />
|
||||
|
||||
<ListView
|
||||
android:id="@+id/favourite"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="8dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.PullStaggeredGridView
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:divider="@null"
|
||||
android:listSelector="@android:color/transparent"
|
||||
android:cacheColorHint="@color/list_main_bg" >
|
||||
</ListView>
|
||||
|
||||
app:item_margin="8dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.RefreshTextView
|
||||
android:id="@+id/refresh_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center_horizontal"
|
||||
android:textColor="@android:color/holo_blue_dark"
|
||||
android:textSize="24sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Hippo Seven
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
|
||||
<com.hippo.ehviewer.widget.LoadImageView
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="@dimen/list_thumb_width"
|
||||
android:layout_height="@dimen/list_thumb_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
style="@style/CardTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_toRightOf="@id/thumb" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploader"
|
||||
style="@style/CardSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/name"
|
||||
android:layout_below="@id/name"
|
||||
android:layout_marginTop="2dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.RatingView
|
||||
android:id="@+id/rate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/name"
|
||||
android:layout_below="@id/uploader"
|
||||
android:layout_marginTop="4dp" />
|
||||
|
||||
<!-- RelativeLayout layout_marginBottom layout_below -->
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@id/name"
|
||||
android:layout_alignParentBottom="true" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category"
|
||||
style="@style/CardSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:paddingTop="2dp"
|
||||
android:textColor="@android:color/white" />
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/posted"
|
||||
style="@style/CardSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginRight="4dp" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Hippo Seven
|
||||
|
||||
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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<com.hippo.ehviewer.widget.LoadImageView
|
||||
android:id="@+id/thumb"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/category"
|
||||
style="@style/CardSubtitle"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
+14
-3
@@ -14,22 +14,33 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
|
||||
<item android:id="@+id/action_search"
|
||||
android:title="@android:string/search_go"
|
||||
android:icon="@drawable/ic_action_search"
|
||||
android:showAsAction="collapseActionView|ifRoom"
|
||||
android:actionViewClass="android.widget.SearchView" />
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/action_refresh"
|
||||
android:showAsAction="never"
|
||||
android:icon="@drawable/ic_action_refresh"
|
||||
android:title="@string/action_refresh"/>
|
||||
|
||||
|
||||
<item
|
||||
android:id="@+id/action_jump"
|
||||
android:showAsAction="never"
|
||||
android:icon="@drawable/ic_action_jump"
|
||||
android:title="@string/jump"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_detail"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/list_mode_detail"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_thumb"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/list_mode_thumb"/>
|
||||
|
||||
</menu>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="StaggeredGridView">
|
||||
<attr name="column_count" format="integer" />
|
||||
<attr name="column_count_portrait" format="integer" />
|
||||
<attr name="column_count_landscape" format="integer" />
|
||||
<attr name="item_margin" format="dimension" />
|
||||
<attr name="grid_paddingLeft" format="dimension" />
|
||||
<attr name="grid_paddingRight" format="dimension" />
|
||||
<attr name="grid_paddingTop" format="dimension" />
|
||||
<attr name="grid_paddingBottom" format="dimension" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
@@ -18,20 +18,20 @@
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/theme_display_settings_title">
|
||||
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="random_theme_color"
|
||||
android:title="@string/random_theme_color_title"
|
||||
android:summaryOn="@string/random_theme_color_summary_on"
|
||||
android:summaryOff="@string/random_theme_color_summary_off"
|
||||
android:defaultValue="true" />
|
||||
|
||||
|
||||
<com.hippo.ehviewer.preference.ColorPreference
|
||||
android:key="theme_color"
|
||||
android:title="@string/theme_color_title" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/screen_display_settings_title">
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
android:entryValues="@array/screen_orientation_entry_values"
|
||||
android:defaultValue="0"
|
||||
android:summary="%s" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/read_display_settings_title">
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
android:entryValues="@array/page_scaling_entry_values"
|
||||
android:defaultValue="3"
|
||||
android:summary="%s" />
|
||||
|
||||
|
||||
<com.hippo.ehviewer.preference.AutoListPreference
|
||||
android:key="start_position"
|
||||
android:title="@string/start_position_title"
|
||||
@@ -63,12 +63,12 @@
|
||||
android:entryValues="@array/start_position_values"
|
||||
android:defaultValue="1"
|
||||
android:summary="%s" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/list_display_settings_title">
|
||||
|
||||
|
||||
<com.hippo.ehviewer.preference.AutoListPreference
|
||||
android:key="list_mode"
|
||||
android:title="@string/list_mode_title"
|
||||
@@ -76,17 +76,17 @@
|
||||
android:entryValues="@array/list_mode_entry_values"
|
||||
android:defaultValue="0"
|
||||
android:summary="%s" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/popular_display_settings_title">
|
||||
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="show_popular_update_time"
|
||||
android:title="@string/show_popular_update_time_title"
|
||||
android:defaultValue="false" />
|
||||
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Etsy
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.etsy.android.grid;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link android.os.Parcelable} implementation that should be used by inheritance
|
||||
* hierarchies to ensure the state of all classes along the chain is saved.
|
||||
*/
|
||||
public abstract class ClassLoaderSavedState implements Parcelable {
|
||||
public static final ClassLoaderSavedState EMPTY_STATE = new ClassLoaderSavedState() {};
|
||||
|
||||
private Parcelable mSuperState = EMPTY_STATE;
|
||||
private ClassLoader mClassLoader;
|
||||
|
||||
/**
|
||||
* Constructor used to make the EMPTY_STATE singleton
|
||||
*/
|
||||
private ClassLoaderSavedState() {
|
||||
mSuperState = null;
|
||||
mClassLoader = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor called by derived classes when creating their ListSavedState objects
|
||||
*
|
||||
* @param superState The state of the superclass of this view
|
||||
*/
|
||||
protected ClassLoaderSavedState(Parcelable superState, ClassLoader classLoader) {
|
||||
mClassLoader = classLoader;
|
||||
if (superState == null) {
|
||||
throw new IllegalArgumentException("superState must not be null");
|
||||
}
|
||||
else {
|
||||
mSuperState = superState != EMPTY_STATE ? superState : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used when reading from a parcel. Reads the state of the superclass.
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
protected ClassLoaderSavedState(Parcel source) {
|
||||
// ETSY : we're using the passed super class loader unlike AbsSavedState
|
||||
Parcelable superState = source.readParcelable(mClassLoader);
|
||||
mSuperState = superState != null ? superState : EMPTY_STATE;
|
||||
}
|
||||
|
||||
final public Parcelable getSuperState() {
|
||||
return mSuperState;
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mSuperState, flags);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<ClassLoaderSavedState> CREATOR
|
||||
= new Parcelable.Creator<ClassLoaderSavedState>() {
|
||||
|
||||
public ClassLoaderSavedState createFromParcel(Parcel in) {
|
||||
Parcelable superState = in.readParcelable(null);
|
||||
if (superState != null) {
|
||||
throw new IllegalStateException("superState must be null");
|
||||
}
|
||||
return EMPTY_STATE;
|
||||
}
|
||||
|
||||
public ClassLoaderSavedState[] newArray(int size) {
|
||||
return new ClassLoaderSavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.etsy.android.grid;
|
||||
|
||||
import android.database.DataSetObserver;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.WrapperListAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* ListAdapter used when a ListView 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.
|
||||
*/
|
||||
public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
|
||||
|
||||
private final ListAdapter mAdapter;
|
||||
|
||||
// These two ArrayList are assumed to NOT be null.
|
||||
// They are indeed created when declared in ListView and then shared.
|
||||
ArrayList<StaggeredGridView.FixedViewInfo> mHeaderViewInfos;
|
||||
ArrayList<StaggeredGridView.FixedViewInfo> mFooterViewInfos;
|
||||
|
||||
// Used as a placeholder in case the provided info views are indeed null.
|
||||
// Currently only used by some CTS tests, which may be removed.
|
||||
static final ArrayList<StaggeredGridView.FixedViewInfo> EMPTY_INFO_LIST =
|
||||
new ArrayList<StaggeredGridView.FixedViewInfo>();
|
||||
|
||||
boolean mAreAllFixedViewsSelectable;
|
||||
|
||||
private final boolean mIsFilterable;
|
||||
|
||||
public HeaderViewListAdapter(ArrayList<StaggeredGridView.FixedViewInfo> headerViewInfos,
|
||||
ArrayList<StaggeredGridView.FixedViewInfo> footerViewInfos,
|
||||
ListAdapter adapter) {
|
||||
mAdapter = adapter;
|
||||
mIsFilterable = adapter instanceof Filterable;
|
||||
|
||||
if (headerViewInfos == null) {
|
||||
mHeaderViewInfos = EMPTY_INFO_LIST;
|
||||
} else {
|
||||
mHeaderViewInfos = headerViewInfos;
|
||||
}
|
||||
|
||||
if (footerViewInfos == null) {
|
||||
mFooterViewInfos = EMPTY_INFO_LIST;
|
||||
} else {
|
||||
mFooterViewInfos = footerViewInfos;
|
||||
}
|
||||
|
||||
mAreAllFixedViewsSelectable =
|
||||
areAllListInfosSelectable(mHeaderViewInfos)
|
||||
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||
}
|
||||
|
||||
public int getHeadersCount() {
|
||||
return mHeaderViewInfos.size();
|
||||
}
|
||||
|
||||
public int getFootersCount() {
|
||||
return mFooterViewInfos.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mAdapter == null || mAdapter.isEmpty();
|
||||
}
|
||||
|
||||
private boolean areAllListInfosSelectable(ArrayList<StaggeredGridView.FixedViewInfo> infos) {
|
||||
if (infos != null) {
|
||||
for (StaggeredGridView.FixedViewInfo info : infos) {
|
||||
if (!info.isSelectable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean removeHeader(View v) {
|
||||
for (int i = 0; i < mHeaderViewInfos.size(); i++) {
|
||||
StaggeredGridView.FixedViewInfo info = mHeaderViewInfos.get(i);
|
||||
if (info.view == v) {
|
||||
mHeaderViewInfos.remove(i);
|
||||
|
||||
mAreAllFixedViewsSelectable =
|
||||
areAllListInfosSelectable(mHeaderViewInfos)
|
||||
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeFooter(View v) {
|
||||
for (int i = 0; i < mFooterViewInfos.size(); i++) {
|
||||
StaggeredGridView.FixedViewInfo info = mFooterViewInfos.get(i);
|
||||
if (info.view == v) {
|
||||
mFooterViewInfos.remove(i);
|
||||
|
||||
mAreAllFixedViewsSelectable =
|
||||
areAllListInfosSelectable(mHeaderViewInfos)
|
||||
&& areAllListInfosSelectable(mFooterViewInfos);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
if (mAdapter != null) {
|
||||
return getFootersCount() + getHeadersCount() + mAdapter.getCount();
|
||||
} else {
|
||||
return getFootersCount() + getHeadersCount();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areAllItemsEnabled() {
|
||||
if (mAdapter != null) {
|
||||
return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled(int position) {
|
||||
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
|
||||
int numHeaders = getHeadersCount();
|
||||
if (position < numHeaders) {
|
||||
return mHeaderViewInfos.get(position).isSelectable;
|
||||
}
|
||||
|
||||
// Adapter
|
||||
final int adjPosition = position - numHeaders;
|
||||
int adapterCount = 0;
|
||||
if (mAdapter != null) {
|
||||
adapterCount = mAdapter.getCount();
|
||||
if (adjPosition < adapterCount) {
|
||||
return mAdapter.isEnabled(adjPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
|
||||
return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable;
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
|
||||
int numHeaders = getHeadersCount();
|
||||
if (position < numHeaders) {
|
||||
return mHeaderViewInfos.get(position).data;
|
||||
}
|
||||
|
||||
// Adapter
|
||||
final int adjPosition = position - numHeaders;
|
||||
int adapterCount = 0;
|
||||
if (mAdapter != null) {
|
||||
adapterCount = mAdapter.getCount();
|
||||
if (adjPosition < adapterCount) {
|
||||
return mAdapter.getItem(adjPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
|
||||
return mFooterViewInfos.get(adjPosition - adapterCount).data;
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
int numHeaders = getHeadersCount();
|
||||
if (mAdapter != null && position >= numHeaders) {
|
||||
int adjPosition = position - numHeaders;
|
||||
int adapterCount = mAdapter.getCount();
|
||||
if (adjPosition < adapterCount) {
|
||||
return mAdapter.getItemId(adjPosition);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean hasStableIds() {
|
||||
if (mAdapter != null) {
|
||||
return mAdapter.hasStableIds();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
// Header (negative positions will throw an ArrayIndexOutOfBoundsException)
|
||||
int numHeaders = getHeadersCount();
|
||||
if (position < numHeaders) {
|
||||
return mHeaderViewInfos.get(position).view;
|
||||
}
|
||||
|
||||
// Adapter
|
||||
final int adjPosition = position - numHeaders;
|
||||
int adapterCount = 0;
|
||||
if (mAdapter != null) {
|
||||
adapterCount = mAdapter.getCount();
|
||||
if (adjPosition < adapterCount) {
|
||||
return mAdapter.getView(adjPosition, convertView, parent);
|
||||
}
|
||||
}
|
||||
|
||||
// Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException)
|
||||
return mFooterViewInfos.get(adjPosition - adapterCount).view;
|
||||
}
|
||||
|
||||
public int getItemViewType(int position) {
|
||||
int numHeaders = getHeadersCount();
|
||||
if (mAdapter != null && position >= numHeaders) {
|
||||
int adjPosition = position - numHeaders;
|
||||
int adapterCount = mAdapter.getCount();
|
||||
if (adjPosition < adapterCount) {
|
||||
return mAdapter.getItemViewType(adjPosition);
|
||||
}
|
||||
}
|
||||
|
||||
return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
|
||||
}
|
||||
|
||||
public int getViewTypeCount() {
|
||||
if (mAdapter != null) {
|
||||
return mAdapter.getViewTypeCount();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void registerDataSetObserver(DataSetObserver observer) {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.registerDataSetObserver(observer);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||
if (mAdapter != null) {
|
||||
mAdapter.unregisterDataSetObserver(observer);
|
||||
}
|
||||
}
|
||||
|
||||
public Filter getFilter() {
|
||||
if (mIsFilterable) {
|
||||
return ((Filterable) mAdapter).getFilter();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ListAdapter getWrappedAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,45 @@
|
||||
package com.etsy.android.grid.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* An {@link android.widget.ImageView} layout that maintains a consistent width to height aspect ratio.
|
||||
*/
|
||||
public class DynamicHeightImageView extends ImageView {
|
||||
|
||||
private double mHeightRatio;
|
||||
|
||||
public DynamicHeightImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DynamicHeightImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setHeightRatio(double ratio) {
|
||||
if (ratio != mHeightRatio) {
|
||||
mHeightRatio = ratio;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public double getHeightRatio() {
|
||||
return mHeightRatio;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mHeightRatio > 0.0) {
|
||||
// set the image views size
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = (int) (width * mHeightRatio);
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
else {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.etsy.android.grid.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
*
|
||||
* A {@link android.widget.TextView} that maintains a consistent width to height aspect ratio.
|
||||
* In the real world this would likely extend ImageView.
|
||||
*/
|
||||
public class DynamicHeightTextView extends TextView {
|
||||
|
||||
private double mHeightRatio;
|
||||
|
||||
public DynamicHeightTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DynamicHeightTextView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setHeightRatio(double ratio) {
|
||||
if (ratio != mHeightRatio) {
|
||||
mHeightRatio = ratio;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public double getHeightRatio() {
|
||||
return mHeightRatio;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mHeightRatio > 0.0) {
|
||||
// set the image views size
|
||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int height = (int) (width * mHeightRatio);
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
else {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1244,7 +1244,7 @@ public class EhClient {
|
||||
|
||||
// modifyFavorite
|
||||
public interface OnModifyFavoriteListener {
|
||||
void onSuccess(List<GalleryInfo> gis, int maxPage);
|
||||
void onSuccess(List<GalleryInfo> gis, int pageNum);
|
||||
void onFailure(String eMsg);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.tile;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class RectDrawable extends Drawable {
|
||||
|
||||
private final int mColor;
|
||||
|
||||
public RectDrawable(int color) {
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.drawColor(mColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
// Empty
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.tile;
|
||||
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.view.View;
|
||||
|
||||
public class TileSalon {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void reform(View view, int backgroundColor) {
|
||||
view.setBackgroundDrawable(new RectDrawable(backgroundColor));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void reform(View view, int[][] stateSets, int[] backgroundColors) {
|
||||
StateListDrawable background = new StateListDrawable();
|
||||
for (int i = 0; i < stateSets.length; i++) {
|
||||
RectDrawable part = new RectDrawable(backgroundColors[i]);
|
||||
background.addState(stateSets[i], part);
|
||||
}
|
||||
view.setBackgroundDrawable(background);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,8 @@ public abstract class AbstractFragmentActivity extends FragmentActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +46,8 @@ public abstract class AbstractFragmentActivity extends FragmentActivity {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,36 +22,27 @@ import java.util.List;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.AppContext;
|
||||
import com.hippo.ehviewer.ImageLoader;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.cache.ImageCache;
|
||||
import com.hippo.ehviewer.cardview.CardViewSalon;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.ehclient.EhClient;
|
||||
import com.hippo.ehviewer.ehclient.ListParser;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
import com.hippo.ehviewer.widget.FswView;
|
||||
import com.hippo.ehviewer.widget.HfListView;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
|
||||
import com.hippo.ehviewer.widget.RatingView;
|
||||
import com.hippo.ehviewer.widget.PullViewGroup;
|
||||
import com.hippo.ehviewer.widget.RefreshTextView;
|
||||
import com.hippo.ehviewer.widget.SuperToast;
|
||||
|
||||
public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
implements HfListView.OnFooterRefreshListener,
|
||||
HfListView.OnRefreshListener {
|
||||
implements PullViewGroup.OnFooterRefreshListener,
|
||||
PullViewGroup.OnRefreshListener {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = AbstractGalleryActivity.class.getSimpleName();
|
||||
|
||||
@@ -62,14 +53,12 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
|
||||
protected AppContext mAppContext;
|
||||
protected EhClient mClient;
|
||||
private ImageLoader mImageLoader;
|
||||
|
||||
private List<GalleryInfo> mGiList;
|
||||
private GalleryAdapter mGalleryAdapter;
|
||||
|
||||
private RelativeLayout mMainView;
|
||||
private HfListView mHlv;
|
||||
private ListView mList;
|
||||
private PullViewGroup mPullViewGroup;
|
||||
private AbsListView mContentView;
|
||||
private RefreshTextView mRefreshTextView;
|
||||
|
||||
private long mTaskStamp;
|
||||
@@ -105,8 +94,23 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
* @return
|
||||
*/
|
||||
protected abstract String getTargetUrl(int targetPage);
|
||||
|
||||
/**
|
||||
* Do get gallarys here, you shuold invoke the onSuccess or
|
||||
* onFailure of listener when over
|
||||
*
|
||||
* @param url
|
||||
* @param taskStamp
|
||||
* @param listener
|
||||
*/
|
||||
protected abstract void doGetGallerys(String url, long taskStamp, OnGetListListener listener);
|
||||
|
||||
/**
|
||||
* Get the layout resources
|
||||
* @return
|
||||
*/
|
||||
protected abstract int getLayoutRes();
|
||||
|
||||
private void getGallerys() {
|
||||
setGallerysLayout();
|
||||
|
||||
@@ -137,20 +141,20 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
}
|
||||
|
||||
public void onlyShowList() {
|
||||
mHlv.setVisibility(View.VISIBLE);
|
||||
mPullViewGroup.setVisibility(View.VISIBLE);
|
||||
mRefreshTextView.setRefreshing(false);
|
||||
mRefreshTextView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void onlyShowNone() {
|
||||
mHlv.setVisibility(View.GONE);
|
||||
mPullViewGroup.setVisibility(View.GONE);
|
||||
mRefreshTextView.setVisibility(View.VISIBLE);
|
||||
mRefreshTextView.setEmesg(R.string.none, false);
|
||||
}
|
||||
|
||||
protected void firstTimeRefresh() {
|
||||
// set mHlv gone, make wait view show
|
||||
mHlv.setVisibility(View.GONE);
|
||||
// set mPullViewGroup gone, make wait view show
|
||||
mPullViewGroup.setVisibility(View.GONE);
|
||||
mRefreshTextView.setVisibility(View.VISIBLE);
|
||||
mRefreshTextView.setRefreshing(true);
|
||||
|
||||
@@ -158,12 +162,12 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
}
|
||||
|
||||
private void setGallerysLayout() {
|
||||
if (mHlv.getVisibility() == View.VISIBLE) {
|
||||
if (mPullViewGroup.getVisibility() == View.VISIBLE) {
|
||||
if (!isFootRefresh)
|
||||
mHlv.setRefreshing(true);
|
||||
mPullViewGroup.setRefreshing(true);
|
||||
mRefreshTextView.setVisibility(View.GONE);
|
||||
} else {
|
||||
mHlv.setVisibility(View.GONE);
|
||||
mPullViewGroup.setVisibility(View.GONE);
|
||||
mRefreshTextView.setVisibility(View.VISIBLE);
|
||||
mRefreshTextView.setRefreshing(true);
|
||||
}
|
||||
@@ -246,18 +250,17 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.list);
|
||||
setContentView(getLayoutRes());
|
||||
|
||||
mAppContext = (AppContext)getApplication();
|
||||
mClient = mAppContext.getEhClient();
|
||||
mImageLoader = ImageLoader.getInstance(this);
|
||||
|
||||
mGiList = new ArrayList<GalleryInfo>();
|
||||
|
||||
mMainView = (RelativeLayout)findViewById(R.id.main);
|
||||
mHlv = (HfListView)findViewById(R.id.list);
|
||||
mHlv.setAgainstToChildPadding(true);
|
||||
mList = mHlv.getListView();
|
||||
mPullViewGroup = (PullViewGroup)findViewById(R.id.list);
|
||||
mPullViewGroup.setAgainstToChildPadding(true);
|
||||
mContentView = mPullViewGroup.getContentView();
|
||||
mRefreshTextView = (RefreshTextView)findViewById(R.id.refresh_text);
|
||||
|
||||
FswView alignment = (FswView)findViewById(R.id.alignment);
|
||||
@@ -267,27 +270,24 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
public void onfitSystemWindows(int paddingLeft, int paddingTop,
|
||||
int paddingRight, int paddingBottom) {
|
||||
mPaddingTop = paddingTop;
|
||||
mList.setPadding(mList.getPaddingLeft(), paddingTop,
|
||||
mList.getPaddingRight(), paddingBottom);
|
||||
mContentView.setPadding(mContentView.getPaddingLeft(), paddingTop,
|
||||
mContentView.getPaddingRight(), paddingBottom);
|
||||
}
|
||||
});
|
||||
|
||||
mHlv.setColorScheme(R.color.refresh_color_1,
|
||||
mPullViewGroup.setColorScheme(R.color.refresh_color_1,
|
||||
R.color.refresh_color_2,
|
||||
R.color.refresh_color_3,
|
||||
R.color.refresh_color_4);
|
||||
mHlv.setOnHeaderRefreshListener(this);
|
||||
mHlv.setOnFooterRefreshListener(this);
|
||||
mHlv.setFooterString(getString(R.string.footer_loading),
|
||||
mPullViewGroup.setOnHeaderRefreshListener(this);
|
||||
mPullViewGroup.setOnFooterRefreshListener(this);
|
||||
mPullViewGroup.setFooterString(getString(R.string.footer_loading),
|
||||
getString(R.string.footer_loaded),
|
||||
getString(R.string.footer_fail));
|
||||
|
||||
mGalleryAdapter = new GalleryAdapter();
|
||||
mList.setAdapter(mGalleryAdapter);
|
||||
mList.setOnScrollListener(new ScrollListener());
|
||||
mList.setDivider(null);
|
||||
mList.setSelector(new ColorDrawable(Color.TRANSPARENT));
|
||||
mList.setClipToPadding(false);
|
||||
mContentView.setOnScrollListener(new ScrollListener());
|
||||
mContentView.setSelector(new ColorDrawable(Color.TRANSPARENT));
|
||||
mContentView.setClipToPadding(false);
|
||||
|
||||
mRefreshTextView.setDefaultRefresh("点击重试", new RefreshTextView.OnRefreshListener() { // TODO
|
||||
@Override
|
||||
@@ -301,30 +301,30 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
/**
|
||||
* @return list view
|
||||
*/
|
||||
public ListView getListView() {
|
||||
return mList;
|
||||
public AbsListView getContentView() {
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
public RelativeLayout getMainView() {
|
||||
return mMainView;
|
||||
}
|
||||
|
||||
public HfListView getHlv() {
|
||||
return mHlv;
|
||||
public PullViewGroup getPullViewGroup() {
|
||||
return mPullViewGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if actionbar or footer is refreshing
|
||||
*/
|
||||
public boolean isRefreshing() {
|
||||
return mHlv.isRefreshing();
|
||||
return mPullViewGroup.isRefreshing();
|
||||
}
|
||||
|
||||
public boolean isGetGalleryOk() {
|
||||
return mHlv.getVisibility() == View.VISIBLE;
|
||||
return mPullViewGroup.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
public int getMaxPage() {
|
||||
public int getPageNum() {
|
||||
return mPageNum;
|
||||
}
|
||||
|
||||
@@ -332,111 +332,19 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
return mCurPage;
|
||||
}
|
||||
|
||||
public List<GalleryInfo> getGalleryList() {
|
||||
return mGiList;
|
||||
}
|
||||
|
||||
public GalleryInfo getGalleryInfo(int position) {
|
||||
return mGiList.get(position);
|
||||
}
|
||||
|
||||
public void setGalleryInfos(List<GalleryInfo> gis) {
|
||||
setGalleryInfos(gis, 1);
|
||||
}
|
||||
|
||||
public void setGalleryInfos(List<GalleryInfo> gis, int pageNum) {
|
||||
mGiList = gis;
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = mGiList.size() - 1;
|
||||
mCurPage = 0;
|
||||
mFirstPage = 0;
|
||||
mLastPage = 0;
|
||||
mPageNum = pageNum;
|
||||
mItemPerPage = mGiList.size();
|
||||
|
||||
if (mItemPerPage == 0)
|
||||
onlyShowNone();
|
||||
else
|
||||
onlyShowList();
|
||||
}
|
||||
|
||||
public void notifyDataSetChanged() {
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
if (mGiList.isEmpty())
|
||||
onlyShowNone();
|
||||
}
|
||||
|
||||
protected class GalleryAdapter extends BaseAdapter {
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mGiList.size();
|
||||
}
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mGiList == null ? 0 : mGiList.get(position);
|
||||
}
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
GalleryInfo gi= mGiList.get(position);
|
||||
if (convertView == null || !(convertView instanceof LinearLayout)) {
|
||||
convertView = LayoutInflater.from(AbstractGalleryActivity.this)
|
||||
.inflate(R.layout.list_item, parent, false);
|
||||
CardViewSalon.reform(AbstractGalleryActivity.this.getResources(),
|
||||
((ViewGroup)convertView).getChildAt(0), new int[][]{
|
||||
new int[]{android.R.attr.state_pressed},
|
||||
new int[]{android.R.attr.state_activated},
|
||||
new int[]{}},
|
||||
new int[]{0xff84cae4, 0xff33b5e5, 0xFFFAFAFA});
|
||||
}
|
||||
final LoadImageView thumb = (LoadImageView)convertView.findViewById(R.id.cover);
|
||||
if (!String.valueOf(gi.gid).equals(thumb.getKey())) {
|
||||
// Set margin top 8dp if position is 0, otherwise 4dp
|
||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
|
||||
convertView.findViewById(R.id.card_view).getLayoutParams();
|
||||
if (position == 0)
|
||||
lp.topMargin = Ui.dp2pix(8);
|
||||
else
|
||||
lp.topMargin = Ui.dp2pix(4);
|
||||
|
||||
// Set new thumb
|
||||
thumb.setImageDrawable(null);
|
||||
thumb.setLoadInfo(gi.thumb, String.valueOf(gi.gid));
|
||||
mImageLoader.add(gi.thumb, String.valueOf(gi.gid),
|
||||
new LoadImageView.SimpleImageGetListener(thumb));
|
||||
}
|
||||
// Set manga name
|
||||
TextView name = (TextView) convertView.findViewById(R.id.name);
|
||||
name.setText(gi.title);
|
||||
// Set uploder
|
||||
TextView uploader = (TextView) convertView.findViewById(R.id.uploader);
|
||||
uploader.setText(gi.uploader);
|
||||
// Set category
|
||||
TextView category = (TextView) convertView.findViewById(R.id.category);
|
||||
String newText = Ui.getCategoryText(gi.category);
|
||||
if (!newText.equals(category.getText())) {
|
||||
category.setText(newText);
|
||||
category.setBackgroundColor(Ui.getCategoryColor(gi.category));
|
||||
}
|
||||
// Set star
|
||||
RatingView rate = (RatingView) convertView
|
||||
.findViewById(R.id.rate);
|
||||
rate.setRating(gi.rating);
|
||||
// set posted
|
||||
TextView posted = (TextView) convertView.findViewById(R.id.posted);
|
||||
posted.setText(gi.posted);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private class ScrollListener implements ListView.OnScrollListener {
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem,
|
||||
int visibleItemCount, int totalItemCount) {
|
||||
mHlv.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
|
||||
mPullViewGroup.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
|
||||
|
||||
if (visibleItemCount < 2 || mItemPerPage == 0)
|
||||
return;
|
||||
@@ -469,19 +377,19 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
|
||||
private void setListPosition(int position) {
|
||||
if (position == 0)
|
||||
mList.setSelectionFromTop(position, mPaddingTop);
|
||||
mPullViewGroup.setSelectionFromTop(position, mPaddingTop);
|
||||
else
|
||||
mList.setSelectionFromTop(position, 0);
|
||||
mPullViewGroup.setSelectionFromTop(position, 0);
|
||||
}
|
||||
|
||||
public interface OnGetListListener {
|
||||
public void onSuccess(long taskStamp, List<GalleryInfo> gis, int maxPage);
|
||||
public void onFailure(long taskStamp, String eMsg);
|
||||
public void onSuccess(BaseAdapter adapter, long taskStamp, List<GalleryInfo> gis, int maxPage);
|
||||
public void onFailure(BaseAdapter adapter, long taskStamp, String eMsg);
|
||||
}
|
||||
|
||||
private final OnGetListListener mListener = new OnGetListListener() {
|
||||
@Override
|
||||
public void onSuccess(long taskStamp,
|
||||
public void onSuccess(BaseAdapter adapter, long taskStamp,
|
||||
List<GalleryInfo> gis, int pageNum) {
|
||||
if (mTaskStamp != taskStamp)
|
||||
return;
|
||||
@@ -495,13 +403,13 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
if (mItemPerPage < itemPerPage)
|
||||
mItemPerPage = itemPerPage;
|
||||
|
||||
if (mPageNum == 0) {
|
||||
if (mPageNum == 0) { // Get none
|
||||
onlyShowNone();
|
||||
|
||||
mFirstPage = 0;
|
||||
mLastPage = 0;
|
||||
mGiList = gis;
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
mGiList.clear();
|
||||
adapter.notifyDataSetChanged();
|
||||
} else {
|
||||
onlyShowList();
|
||||
|
||||
@@ -509,8 +417,9 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
case MODE_REFRESH:
|
||||
mFirstPage = 0;
|
||||
mLastPage = 0;
|
||||
mGiList = gis;
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
mGiList.clear();
|
||||
mGiList.addAll(gis);
|
||||
adapter.notifyDataSetChanged();
|
||||
// For current page
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = gis.size() - 1;
|
||||
@@ -522,14 +431,14 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
case MODE_PRE_PAGE:
|
||||
mFirstPage--;
|
||||
mGiList.addAll(0, gis);
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
if (mIsKeepPosition) {
|
||||
mFirstIndex += gis.size();
|
||||
mLastIndex += gis.size();
|
||||
int position = mList.getFirstVisiblePosition() + gis.size();
|
||||
int position = mContentView.getFirstVisiblePosition() + gis.size();
|
||||
setListPosition(position);
|
||||
mList.smoothScrollToPosition(position -1);
|
||||
mContentView.smoothScrollToPosition(position -1);
|
||||
} else {
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = gis.size()-1;
|
||||
@@ -541,7 +450,7 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
case MODE_NEXT_PAGE:
|
||||
mLastPage++;
|
||||
mGiList.addAll(gis);
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
adapter.notifyDataSetChanged();
|
||||
if (!mIsKeepPosition) {
|
||||
mFirstIndex = mGiList.size() - gis.size();
|
||||
mLastIndex = mGiList.size() - 1;
|
||||
@@ -553,8 +462,9 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
case MODE_SOMEWHERE:
|
||||
mFirstPage = mTargetPage;
|
||||
mLastPage = mTargetPage;
|
||||
mGiList = gis;
|
||||
mGalleryAdapter.notifyDataSetChanged();
|
||||
mGiList.clear();
|
||||
mGiList.addAll(gis);
|
||||
adapter.notifyDataSetChanged();
|
||||
// For current page
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = gis.size() - 1;
|
||||
@@ -564,17 +474,17 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
}
|
||||
}
|
||||
|
||||
mHlv.setAnyRefreshComplete(true);
|
||||
mPullViewGroup.setAnyRefreshComplete(true);
|
||||
}
|
||||
@Override
|
||||
public void onFailure(long taskStamp, String eMsg) {
|
||||
public void onFailure(BaseAdapter adapter, long taskStamp, String eMsg) {
|
||||
if (mTaskStamp != taskStamp)
|
||||
return;
|
||||
|
||||
switch (mGetMode) {
|
||||
case MODE_REFRESH:
|
||||
case MODE_SOMEWHERE:
|
||||
mHlv.setVisibility(View.GONE);
|
||||
mPullViewGroup.setVisibility(View.GONE);
|
||||
mRefreshTextView.setVisibility(View.VISIBLE);
|
||||
if (eMsg.equals("index error")) {
|
||||
mRefreshTextView.setEmesg(eMsg, "点击回第一页", // TODO
|
||||
@@ -594,7 +504,7 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
|
||||
mRefreshTextView.setVisibility(View.GONE);
|
||||
new SuperToast(AbstractGalleryActivity.this, eMsg, SuperToast.ERROR).show();
|
||||
}
|
||||
mHlv.setAnyRefreshComplete(false);
|
||||
mPullViewGroup.setAnyRefreshComplete(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -30,7 +30,8 @@ public class AbstractPreferenceActivity extends PreferenceActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,7 +45,8 @@ public class AbstractPreferenceActivity extends PreferenceActivity {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,7 +31,8 @@ public class AbstractSlidingActivity extends SlidingActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,7 +46,8 @@ public class AbstractSlidingActivity extends SlidingActivity {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Ui.adjustOrientation(this, true);
|
||||
Ui.adjustOrientation(this);
|
||||
Ui.updateTranslucent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Set;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@@ -43,12 +44,15 @@ import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.AppContext;
|
||||
import com.hippo.ehviewer.ImageLoader;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.cardview.CardViewSalon;
|
||||
import com.hippo.ehviewer.data.Data;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.ehclient.EhClient;
|
||||
@@ -62,9 +66,11 @@ import com.hippo.ehviewer.widget.ActionableToastBar;
|
||||
import com.hippo.ehviewer.widget.ActionableToastBar.ActionClickedListener;
|
||||
import com.hippo.ehviewer.widget.DialogBuilder;
|
||||
import com.hippo.ehviewer.widget.FswView;
|
||||
import com.hippo.ehviewer.widget.HfListView;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
|
||||
import com.hippo.ehviewer.widget.ProgressDialogBulider;
|
||||
import com.hippo.ehviewer.widget.PullViewGroup;
|
||||
import com.hippo.ehviewer.widget.RatingView;
|
||||
import com.hippo.ehviewer.widget.SuperToast;
|
||||
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
|
||||
|
||||
@@ -74,13 +80,16 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "FavouriteActivity";
|
||||
|
||||
private static final String LOCAL_FAVORITE_URL = "local_favorite://all";
|
||||
|
||||
private Data mData;
|
||||
private Resources mResources;
|
||||
private EhClient mClient;
|
||||
|
||||
private RelativeLayout mMainView;
|
||||
private HfListView mHlv;
|
||||
private PullViewGroup mPullViewGroup;
|
||||
private ListView mList;
|
||||
private BaseAdapter mAdapter;
|
||||
|
||||
private SlidingMenu mSlidingMenu;
|
||||
private ListView mMenuList;
|
||||
@@ -97,6 +106,9 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
private ProgressDialogBulider mPdb;
|
||||
private AlertDialog mProgressDialog;
|
||||
|
||||
private List<GalleryInfo> mLastModifyGiList = null;
|
||||
private int mLastModifyPageNum = 0;
|
||||
|
||||
private final DownloadServiceConnection mServiceConn = new DownloadServiceConnection();
|
||||
|
||||
@Override
|
||||
@@ -113,23 +125,24 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
}
|
||||
|
||||
private void initLocalFavorite() {
|
||||
mHlv.setEnabledHeader(false);
|
||||
mHlv.setEnabledFooter(false);
|
||||
mPullViewGroup.setEnabledHeader(false);
|
||||
mPullViewGroup.setEnabledFooter(false);
|
||||
setTitle(Favorite.FAVORITE_TITLES[mMenuIndex]);
|
||||
setGalleryInfos(mData.getAllLocalFavourites());
|
||||
if (mData.getAllLocalFavourites().isEmpty())
|
||||
onlyShowNone();
|
||||
else
|
||||
onlyShowList();
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void initFavorite() {
|
||||
mHlv.setEnabledHeader(true);
|
||||
mHlv.setEnabledFooter(true);
|
||||
mPullViewGroup.setEnabledHeader(true);
|
||||
mPullViewGroup.setEnabledFooter(true);
|
||||
setTitle(Favorite.FAVORITE_TITLES[mMenuIndex]);
|
||||
refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutRes() {
|
||||
return R.layout.favorite_list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -158,8 +171,8 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
|
||||
// Get View
|
||||
mMainView = getMainView();
|
||||
mHlv = getHlv();
|
||||
mList = getListView();
|
||||
mPullViewGroup = getPullViewGroup();
|
||||
mList = (ListView)getContentView();
|
||||
mMenuList = (ListView)findViewById(R.id.favorite_menu_list);
|
||||
|
||||
mActionableToastBar = new ActionableToastBar(this);
|
||||
@@ -167,11 +180,10 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
mMainView.addView(mActionableToastBar);
|
||||
mMainView.setOnTouchListener(this);
|
||||
|
||||
mMenuIndex = 0;
|
||||
initLocalFavorite();
|
||||
|
||||
mChoiceGiSet = new LinkedHashSet<GalleryInfo>();
|
||||
mChoiceGiSetCopy = new LinkedHashSet<GalleryInfo>();
|
||||
|
||||
mList.setDivider(null);
|
||||
mList.setOnTouchListener(this);
|
||||
mList.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
@@ -187,6 +199,8 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
});
|
||||
mList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
|
||||
mList.setMultiChoiceModeListener(this);
|
||||
mAdapter = new ListAdapter(this, getGalleryList());
|
||||
mList.setAdapter(mAdapter);
|
||||
|
||||
mMenuList.setClipToPadding(false);
|
||||
mMenuList.setAdapter(new BaseAdapter() {
|
||||
@@ -286,6 +300,10 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
superToast.setDuration(SuperToast.LENGTH_LONG);
|
||||
superToast.show();
|
||||
}
|
||||
|
||||
// TODO Should show default favourite
|
||||
mMenuIndex = 0;
|
||||
initLocalFavorite();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -391,7 +409,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
}
|
||||
@Override
|
||||
public void onFailure(String eMsg) {
|
||||
notifyDataSetChanged();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mPdb = null;
|
||||
mProgressDialog.dismiss();
|
||||
mProgressDialog = null;
|
||||
@@ -405,7 +423,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
}
|
||||
});
|
||||
} else {
|
||||
notifyDataSetChanged();
|
||||
mAdapter.notifyDataSetChanged();
|
||||
mSetIter = null;
|
||||
mPdb = null;
|
||||
mProgressDialog.dismiss();
|
||||
@@ -440,7 +458,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
mClient.modifyFavorite(getGids(mChoiceGiSetCopy), mTargetCat,
|
||||
mMenuIndex -1, new Modify(mResources.getString(R.string.move_successfully),
|
||||
mResources.getString(R.string.failed_to_move), true));
|
||||
mHlv.setRefreshing(true);
|
||||
mPullViewGroup.setRefreshing(true);
|
||||
} else { // change cloud dir
|
||||
mMoveDialog.dismiss();
|
||||
mMoveDialog = null;
|
||||
@@ -448,7 +466,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
mClient.modifyFavorite(getGids(mChoiceGiSetCopy), mTargetCat,
|
||||
mMenuIndex -1, new Modify(mResources.getString(R.string.move_successfully),
|
||||
mResources.getString(R.string.failed_to_move), false));
|
||||
mHlv.setRefreshing(true);
|
||||
mPullViewGroup.setRefreshing(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,13 +486,13 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
if (mMenuIndex == 0) {
|
||||
for (GalleryInfo gi : mChoiceGiSet)
|
||||
mData.deleteLocalFavourite(gi.gid);
|
||||
notifyDataSetChanged();
|
||||
refresh();
|
||||
} else {
|
||||
mTargetCat = -1;
|
||||
mClient.modifyFavorite(getGids(mChoiceGiSet), mTargetCat,
|
||||
mMenuIndex -1, new Modify(mResources.getString(R.string.delete_successfully),
|
||||
mResources.getString(R.string.failed_to_delete), false));
|
||||
mHlv.setRefreshing(true);
|
||||
mPullViewGroup.setRefreshing(true);
|
||||
}
|
||||
mode.finish();
|
||||
return true;
|
||||
@@ -504,23 +522,39 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
|
||||
@Override
|
||||
protected String getTargetUrl(int targetPage) {
|
||||
return mClient.getFavoriteUrl(mMenuIndex-1, targetPage);
|
||||
if (mMenuIndex == 0)
|
||||
return LOCAL_FAVORITE_URL;
|
||||
else
|
||||
return mClient.getFavoriteUrl(mMenuIndex-1, targetPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGetGallerys(String url, final long taskStamp,
|
||||
final OnGetListListener listener) {
|
||||
mClient.getGList(url, Config.getApiMode(), null, new EhClient.OnGetGListListener() {
|
||||
@Override
|
||||
public void onSuccess(Object checkFlag, List<GalleryInfo> giList,
|
||||
int maxPage) {
|
||||
listener.onSuccess(taskStamp, giList, maxPage);
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Object checkFlag, String eMsg) {
|
||||
listener.onFailure(taskStamp, eMsg);
|
||||
}
|
||||
});
|
||||
// If get local favorite
|
||||
if (mLastModifyGiList != null) {
|
||||
listener.onSuccess(mAdapter, taskStamp, mLastModifyGiList, mLastModifyPageNum);
|
||||
mLastModifyGiList = null;
|
||||
mLastModifyPageNum = 0;
|
||||
} else if (LOCAL_FAVORITE_URL.equals(url)) {
|
||||
List<GalleryInfo> giList = mData.getAllLocalFavourites();
|
||||
if (giList == null || giList.size() == 0)
|
||||
listener.onSuccess(mAdapter, taskStamp, giList, 0);
|
||||
else
|
||||
listener.onSuccess(mAdapter, taskStamp, giList, 1);
|
||||
} else { // If get cloud favorite
|
||||
mClient.getGList(url, Config.getApiMode(), null, new EhClient.OnGetGListListener() {
|
||||
@Override
|
||||
public void onSuccess(Object checkFlag, List<GalleryInfo> giList,
|
||||
int maxPage) {
|
||||
listener.onSuccess(mAdapter, taskStamp, giList, maxPage);
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Object checkFlag, String eMsg) {
|
||||
listener.onFailure(mAdapter, taskStamp, eMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private class Modify implements EhClient.OnModifyFavoriteListener {
|
||||
@@ -535,9 +569,10 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<GalleryInfo> gis, int maxPage) {
|
||||
setGalleryInfos(gis, maxPage);
|
||||
mHlv.setRefreshing(false);
|
||||
public void onSuccess(List<GalleryInfo> gis, int pageNum) {
|
||||
mLastModifyGiList = gis;
|
||||
mLastModifyPageNum = pageNum;
|
||||
refresh();
|
||||
new SuperToast(FavouriteActivity.this, mSuccStr).show();
|
||||
|
||||
// add to local
|
||||
@@ -547,7 +582,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
}
|
||||
@Override
|
||||
public void onFailure(String eMsg) {
|
||||
mHlv.setRefreshing(false);
|
||||
mPullViewGroup.setRefreshing(false);
|
||||
showToastBar(new Remodify(mSuccStr, mFailStr, mToLocal), 0, mFailStr + ": " + eMsg,
|
||||
R.drawable.ic_action_redo, mResources.getString(R.string.retry), true);
|
||||
}
|
||||
@@ -574,4 +609,80 @@ public class FavouriteActivity extends AbstractGalleryActivity
|
||||
mClient.modifyFavorite(getGids(mChoiceGiSetCopy), -1, mMenuIndex -1, new Modify(mSuccStr, mFailStr, mToLocal));
|
||||
}
|
||||
}
|
||||
|
||||
public class ListAdapter extends BaseAdapter {
|
||||
private final List<GalleryInfo> mGiList;
|
||||
private final ImageLoader mImageLoader;
|
||||
|
||||
public ListAdapter(Context context, List<GalleryInfo> gilist) {
|
||||
mGiList = gilist;
|
||||
mImageLoader =ImageLoader.getInstance(FavouriteActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mGiList.size();
|
||||
}
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mGiList == null ? 0 : mGiList.get(position);
|
||||
}
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
GalleryInfo gi= mGiList.get(position);
|
||||
if (convertView == null || !(convertView instanceof LinearLayout)) {
|
||||
convertView = LayoutInflater.from(FavouriteActivity.this)
|
||||
.inflate(R.layout.favorite_list_item, parent, false);
|
||||
CardViewSalon.reform(FavouriteActivity.this.getResources(),
|
||||
((ViewGroup)convertView).getChildAt(0), new int[][]{
|
||||
new int[]{android.R.attr.state_pressed},
|
||||
new int[]{android.R.attr.state_activated},
|
||||
new int[]{}},
|
||||
new int[]{0xff84cae4, 0xff33b5e5, 0xFFFAFAFA});
|
||||
}
|
||||
final LoadImageView thumb = (LoadImageView)convertView.findViewById(R.id.cover);
|
||||
if (!String.valueOf(gi.gid).equals(thumb.getKey())) {
|
||||
// Set margin top 8dp if position is 0, otherwise 4dp
|
||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
|
||||
convertView.findViewById(R.id.card_view).getLayoutParams();
|
||||
if (position == 0)
|
||||
lp.topMargin = Ui.dp2pix(8);
|
||||
else
|
||||
lp.topMargin = Ui.dp2pix(4);
|
||||
|
||||
// Set new thumb
|
||||
thumb.setImageDrawable(null);
|
||||
thumb.setLoadInfo(gi.thumb, String.valueOf(gi.gid));
|
||||
mImageLoader.add(gi.thumb, String.valueOf(gi.gid),
|
||||
new LoadImageView.SimpleImageGetListener(thumb).setFixScaleType(true));
|
||||
}
|
||||
// Set manga name
|
||||
TextView name = (TextView) convertView.findViewById(R.id.name);
|
||||
name.setText(gi.title);
|
||||
// Set uploder
|
||||
TextView uploader = (TextView) convertView.findViewById(R.id.uploader);
|
||||
uploader.setText(gi.uploader);
|
||||
// Set category
|
||||
TextView category = (TextView) convertView.findViewById(R.id.category);
|
||||
String newText = Ui.getCategoryText(gi.category);
|
||||
if (!newText.equals(category.getText())) {
|
||||
category.setText(newText);
|
||||
category.setBackgroundColor(Ui.getCategoryColor(gi.category));
|
||||
}
|
||||
// Set star
|
||||
RatingView rate = (RatingView) convertView
|
||||
.findViewById(R.id.rate);
|
||||
rate.setRating(gi.rating);
|
||||
// set posted
|
||||
TextView posted = (TextView) convertView.findViewById(R.id.posted);
|
||||
posted.setText(gi.posted);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActionBar;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.SearchManager;
|
||||
@@ -43,6 +44,7 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.AdapterView.OnItemLongClickListener;
|
||||
@@ -55,15 +57,19 @@ import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.etsy.android.grid.StaggeredGridView;
|
||||
import com.hippo.ehviewer.AppContext;
|
||||
import com.hippo.ehviewer.AppHandler;
|
||||
import com.hippo.ehviewer.ImageLoader;
|
||||
import com.hippo.ehviewer.ListUrls;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.UpdateHelper;
|
||||
import com.hippo.ehviewer.cardview.CardViewSalon;
|
||||
import com.hippo.ehviewer.data.Data;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.Tag;
|
||||
@@ -71,6 +77,7 @@ import com.hippo.ehviewer.ehclient.EhClient;
|
||||
import com.hippo.ehviewer.network.Downloader;
|
||||
import com.hippo.ehviewer.service.DownloadService;
|
||||
import com.hippo.ehviewer.service.DownloadServiceConnection;
|
||||
import com.hippo.ehviewer.tile.TileSalon;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.Favorite;
|
||||
import com.hippo.ehviewer.util.Theme;
|
||||
@@ -80,17 +87,16 @@ import com.hippo.ehviewer.widget.AlertButton;
|
||||
import com.hippo.ehviewer.widget.CategoryTable;
|
||||
import com.hippo.ehviewer.widget.DialogBuilder;
|
||||
import com.hippo.ehviewer.widget.FswView;
|
||||
import com.hippo.ehviewer.widget.LoadImageView;
|
||||
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
|
||||
import com.hippo.ehviewer.widget.PrefixEditText;
|
||||
import com.hippo.ehviewer.widget.RatingView;
|
||||
import com.hippo.ehviewer.widget.SuperDialogUtil;
|
||||
import com.hippo.ehviewer.widget.SuperToast;
|
||||
import com.hippo.ehviewer.widget.TagListView;
|
||||
import com.hippo.ehviewer.widget.TagsAdapter;
|
||||
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
|
||||
|
||||
// TODO check visiblePage is right or not
|
||||
// TODO http://lofi.e-hentai.org/
|
||||
|
||||
/*
|
||||
*
|
||||
* Footer 显示产生的 refresh 手动 pull 显示产生的 refresh 按键或其他产生的 refresh
|
||||
@@ -118,7 +124,8 @@ import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
|
||||
public class GalleryListActivity extends AbstractGalleryActivity
|
||||
implements View.OnClickListener {
|
||||
|
||||
private static final String TAG = "MangaListActivity";
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = GalleryListActivity.class.getSimpleName();
|
||||
|
||||
public static final String ACTION_GALLERY_LIST = "com.hippo.ehviewer.intent.action.GALLERY_LIST";
|
||||
|
||||
@@ -127,6 +134,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
public static final String KEY_TAG = "tag";
|
||||
public static final String KEY_UPLOADER = "uploader";
|
||||
|
||||
public static final int LIST_MODE_DETAIL = 0x0;
|
||||
public static final int LIST_MODE_THUMB = 0x1;
|
||||
|
||||
private EhClient mClient;
|
||||
private Resources mResources;
|
||||
|
||||
@@ -144,7 +154,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
private Button logoutButton;
|
||||
private View waitloginoutView;
|
||||
|
||||
private ListView mList;
|
||||
private StaggeredGridView mStaggeredGridView;
|
||||
private BaseAdapter mAdapter;
|
||||
|
||||
private TagsAdapter tagsAdapter;
|
||||
|
||||
@@ -170,6 +181,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
|
||||
private final DownloadServiceConnection mServiceConn = new DownloadServiceConnection();
|
||||
|
||||
private int mListMode;
|
||||
private int mListModeThumbHeight;
|
||||
|
||||
private void toRegister() {
|
||||
Uri uri = Uri.parse("http://forums.e-hentai.org/index.php?act=Reg");
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW,uri);
|
||||
@@ -492,7 +506,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
TextView tv = (TextView)view.findViewById(R.id.list_jump_sum);
|
||||
// For lofi, can not get page num, so use Integer.MAX_VALUE
|
||||
tv.setText(String.format(getString(R.string.jump_summary), getCurPage() + 1,
|
||||
getMaxPage() == Integer.MAX_VALUE ? "未知" : String.valueOf(getMaxPage()))); // TODO
|
||||
getPageNum() == Integer.MAX_VALUE ? "未知" : String.valueOf(getPageNum()))); // TODO
|
||||
tv = (TextView)view.findViewById(R.id.list_jump_to);
|
||||
tv.setText(R.string.jump_to);
|
||||
final EditText et = (EditText)view.findViewById(R.id.list_jump_edit);
|
||||
@@ -506,6 +520,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
int targetPage;
|
||||
try{
|
||||
targetPage = Integer.parseInt(et.getText().toString()) - 1;
|
||||
if (targetPage < 0 || targetPage >= getPageNum())
|
||||
throw new Exception();
|
||||
} catch(Exception e) {
|
||||
new SuperToast(GalleryListActivity.this, R.string.toast_invalid_page,
|
||||
SuperToast.ERROR).show();
|
||||
@@ -738,6 +754,12 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
tryUpdateGridView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
@@ -805,6 +827,11 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutRes() {
|
||||
return R.layout.gallery_list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -864,7 +891,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
logoutButton = (Button)mUserPanel.findViewById(R.id.logout);
|
||||
waitloginoutView = mUserPanel.findViewById(R.id.wait);
|
||||
|
||||
mList = getListView();
|
||||
mStaggeredGridView = (StaggeredGridView)getContentView();
|
||||
|
||||
loginButton.setOnClickListener(this);
|
||||
registerButton.setOnClickListener(this);
|
||||
@@ -901,6 +928,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
return position;
|
||||
}
|
||||
|
||||
@SuppressLint({ "InflateParams", "ViewHolder" })
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
LayoutInflater li= LayoutInflater.from(GalleryListActivity.this);
|
||||
@@ -1011,7 +1039,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
});
|
||||
|
||||
// Listview
|
||||
mList.setOnItemClickListener(new OnItemClickListener() {
|
||||
mAdapter = new ListAdapter(this, getGalleryList());
|
||||
mStaggeredGridView.setAdapter(mAdapter);
|
||||
mStaggeredGridView.setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> arg0, View arg1,
|
||||
int position, long arg3) {
|
||||
@@ -1023,7 +1053,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
mList.setOnItemLongClickListener(new OnItemLongClickListener() {
|
||||
mStaggeredGridView.setOnItemLongClickListener(new OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
|
||||
int position, long arg3) {
|
||||
@@ -1032,6 +1062,16 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mStaggeredGridView.setOnChangeColumnListener(new StaggeredGridView.OnChangeColumnListener() {
|
||||
@Override
|
||||
public void onChangeColumn(int columnCount, int width) {
|
||||
// Here to get thumb height, width is fixed by column count
|
||||
if (width == 0)
|
||||
width = GalleryListActivity.this.getWindow()
|
||||
.findViewById(Window.ID_ANDROID_CONTENT).getWidth();
|
||||
mListModeThumbHeight = (width - ((columnCount + 1) * Ui.dp2pix(8))) / columnCount / 2 * 3;
|
||||
}
|
||||
});
|
||||
|
||||
FswView alignment = (FswView)findViewById(R.id.alignment);
|
||||
alignment.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
|
||||
@@ -1064,6 +1104,18 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
// Update user panel
|
||||
setUserPanel();
|
||||
|
||||
// Get list mode
|
||||
mListMode = Config.getListMode();
|
||||
switch (mListMode) {
|
||||
case LIST_MODE_DETAIL:
|
||||
mStaggeredGridView.setColumnCountPortraitBefore(1); // TODO
|
||||
mStaggeredGridView.setColumnCountLandscapeBefore(2);
|
||||
break;
|
||||
case LIST_MODE_THUMB:
|
||||
mStaggeredGridView.setColumnCountPortraitBefore(3);
|
||||
mStaggeredGridView.setColumnCountLandscapeBefore(5);
|
||||
}
|
||||
|
||||
// get MangeList
|
||||
firstTimeRefresh();
|
||||
|
||||
@@ -1090,8 +1142,34 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update gird view if necessary
|
||||
*/
|
||||
private void tryUpdateGridView() {
|
||||
int newListMode = Config.getListMode();
|
||||
if (mListMode == newListMode) {
|
||||
return;
|
||||
} else {
|
||||
mListMode = newListMode;
|
||||
updateGridView();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGridView() {
|
||||
switch (mListMode) {
|
||||
case LIST_MODE_DETAIL:
|
||||
mStaggeredGridView.setColumnCountPortrait(1); // TODO
|
||||
mStaggeredGridView.setColumnCountLandscape(2);
|
||||
break;
|
||||
case LIST_MODE_THUMB:
|
||||
mStaggeredGridView.setColumnCountPortrait(3);
|
||||
mStaggeredGridView.setColumnCountLandscape(5);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Do not show menu when mSlidingMenu is shown
|
||||
if (mSlidingMenu!= null && mSlidingMenu.isMenuShowing())
|
||||
return true;
|
||||
|
||||
@@ -1138,15 +1216,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
.getDeclaredField("mCursorDrawableRes");
|
||||
f.setAccessible(true);
|
||||
f.setInt(searchText, searchCursorID);
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
searchText.setTextColor(Color.WHITE);
|
||||
@@ -1201,6 +1271,12 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
voiceView.setImageDrawable(voiceImage);
|
||||
}
|
||||
|
||||
// Hide some menu item
|
||||
if (mListMode == LIST_MODE_DETAIL)
|
||||
menu.removeItem(R.id.action_detail);
|
||||
else if (mListMode == LIST_MODE_THUMB)
|
||||
menu.removeItem(R.id.action_thumb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1235,6 +1311,18 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
if (!isRefreshing() && isGetGalleryOk())
|
||||
jump();
|
||||
return true;
|
||||
case R.id.action_detail:
|
||||
mListMode = LIST_MODE_DETAIL;
|
||||
Config.setListMode(mListMode);
|
||||
updateGridView();
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
case R.id.action_thumb:
|
||||
mListMode = LIST_MODE_THUMB;
|
||||
Config.setListMode(mListMode);
|
||||
updateGridView();
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -1356,7 +1444,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
mClient.getPopular(new EhClient.OnGetPopularListener() {
|
||||
@Override
|
||||
public void onSuccess(List<GalleryInfo> gis, long timeStamp) {
|
||||
listener.onSuccess(taskStamp, gis, gis.size() == 0 ? 0 : 1);
|
||||
listener.onSuccess(mAdapter, taskStamp, gis, gis.size() == 0 ? 0 : 1);
|
||||
// Show update time
|
||||
if (timeStamp != -1 && Config.getShowPopularUpdateTime())
|
||||
new SuperToast(GalleryListActivity.this,
|
||||
@@ -1365,7 +1453,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
}
|
||||
@Override
|
||||
public void onFailure(String eMsg) {
|
||||
listener.onFailure(taskStamp, eMsg);
|
||||
listener.onFailure(mAdapter, taskStamp, eMsg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -1373,13 +1461,104 @@ public class GalleryListActivity extends AbstractGalleryActivity
|
||||
@Override
|
||||
public void onSuccess(Object checkFlag, List<GalleryInfo> lmdArray,
|
||||
int pageNum) {
|
||||
listener.onSuccess(taskStamp, lmdArray, pageNum);
|
||||
listener.onSuccess(mAdapter, taskStamp, lmdArray, pageNum);
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Object checkFlag, String eMsg) {
|
||||
listener.onFailure(taskStamp, eMsg);
|
||||
listener.onFailure(mAdapter, taskStamp, eMsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class ListAdapter extends BaseAdapter {
|
||||
private final List<GalleryInfo> mGiList;
|
||||
private final ImageLoader mImageLoader;
|
||||
|
||||
public ListAdapter(Context context, List<GalleryInfo> gilist) {
|
||||
mGiList = gilist;
|
||||
mImageLoader =ImageLoader.getInstance(GalleryListActivity.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mGiList.size();
|
||||
}
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return mGiList == null ? 0 : mGiList.get(position);
|
||||
}
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
GalleryInfo gi= mGiList.get(position);
|
||||
|
||||
if (convertView == null ||
|
||||
(mListMode == LIST_MODE_DETAIL && !(convertView instanceof RelativeLayout)) ||
|
||||
(mListMode == LIST_MODE_THUMB && !(convertView instanceof LinearLayout))) {
|
||||
// Get new view
|
||||
switch (mListMode) {
|
||||
case LIST_MODE_DETAIL:
|
||||
convertView = LayoutInflater.from(GalleryListActivity.this)
|
||||
.inflate(R.layout.gallery_list_detail_item, parent, false);
|
||||
CardViewSalon.reform(GalleryListActivity.this.getResources(),
|
||||
convertView, new int[][]{
|
||||
new int[]{android.R.attr.state_pressed},
|
||||
new int[]{android.R.attr.state_activated},
|
||||
new int[]{}},
|
||||
new int[]{0xff84cae4, 0xff33b5e5, 0xFFFAFAFA}); // TODO
|
||||
break;
|
||||
case LIST_MODE_THUMB:
|
||||
convertView = LayoutInflater.from(GalleryListActivity.this)
|
||||
.inflate(R.layout.gallery_list_thumb_item, parent, false);
|
||||
TileSalon.reform(convertView, 0xFFFAFAFA); // TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final LoadImageView thumb = (LoadImageView)convertView.findViewById(R.id.thumb);
|
||||
if (!String.valueOf(gi.gid).equals(thumb.getKey())) {
|
||||
// Set height
|
||||
if (mListMode == LIST_MODE_THUMB)
|
||||
thumb.getLayoutParams().height = mListModeThumbHeight;
|
||||
|
||||
// Set new thumb
|
||||
thumb.setImageDrawable(null);
|
||||
thumb.setLoadInfo(gi.thumb, String.valueOf(gi.gid));
|
||||
mImageLoader.add(gi.thumb, String.valueOf(gi.gid),
|
||||
new LoadImageView.SimpleImageGetListener(thumb).setFixScaleType(true));
|
||||
}
|
||||
// Set category
|
||||
TextView category = (TextView) convertView.findViewById(R.id.category);
|
||||
String newText = Ui.getCategoryText(gi.category);
|
||||
if (!newText.equals(category.getText())) {
|
||||
category.setText(newText);
|
||||
category.setBackgroundColor(Ui.getCategoryColor(gi.category));
|
||||
}
|
||||
|
||||
// For detail mode
|
||||
if (mListMode == LIST_MODE_DETAIL) {
|
||||
// Set manga name
|
||||
TextView name = (TextView) convertView.findViewById(R.id.name);
|
||||
name.setText(gi.title);
|
||||
// Set uploder
|
||||
TextView uploader = (TextView) convertView.findViewById(R.id.uploader);
|
||||
uploader.setText(gi.uploader);
|
||||
|
||||
// Set star
|
||||
RatingView rate = (RatingView) convertView
|
||||
.findViewById(R.id.rate);
|
||||
rate.setRating(gi.rating);
|
||||
// set posted
|
||||
TextView posted = (TextView) convertView.findViewById(R.id.posted);
|
||||
posted.setText(gi.posted);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,9 +68,6 @@ public class Config {
|
||||
private static final String KEY_SHOW_POPULAR_UPDATE_TIME = "show_popular_update_time";
|
||||
private static final boolean DEFAULT_SHOW_POPULAR_UPDATE_TIME = false;
|
||||
|
||||
private static final String KEY_LIST_MODE = "list_mode";
|
||||
private static final String DEFAULT_LIST_MODE = "0";
|
||||
|
||||
private static boolean mInit = false;
|
||||
|
||||
private static Context mContext;
|
||||
@@ -301,11 +298,22 @@ public class Config {
|
||||
return mConfigPre.getBoolean(KEY_SHOW_POPULAR_UPDATE_TIME, DEFAULT_SHOW_POPULAR_UPDATE_TIME);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****** Display ******/
|
||||
|
||||
private static final String KEY_LIST_MODE = "list_mode";
|
||||
private static final String DEFAULT_LIST_MODE = "1";
|
||||
|
||||
public static int getListMode() {
|
||||
return Integer.parseInt(mConfigPre.getString(KEY_LIST_MODE, DEFAULT_LIST_MODE));
|
||||
}
|
||||
|
||||
/****** For Mode an API Mode ******/
|
||||
public static void setListMode(int listMode) {
|
||||
mConfigPre.edit().putString(KEY_LIST_MODE, String.valueOf(listMode)).apply();
|
||||
}
|
||||
|
||||
/****** Mode an API Mode ******/
|
||||
|
||||
private static final String KEY_MODE = "mode";
|
||||
private static final int DEFAULT_MODE = EhClient.MODE_G;
|
||||
@@ -329,7 +337,7 @@ public class Config {
|
||||
mConfigPre.edit().putInt(KEY_API_MODE, apiMode).apply();
|
||||
}
|
||||
|
||||
/****** For Eh Config ******/
|
||||
/****** Eh Config ******/
|
||||
|
||||
private static final String KEY_DEFAULT_CAT = "default_cat";
|
||||
private static final int DEFAULT_DEFAULT_CAT = ListUrls.ALL_CATEGORT;
|
||||
|
||||
@@ -284,17 +284,9 @@ public class Ui {
|
||||
}
|
||||
|
||||
public static void adjustOrientation(Activity activity) {
|
||||
adjustOrientation(activity, false);
|
||||
}
|
||||
|
||||
public static void adjustOrientation(Activity activity,
|
||||
boolean updateTranslucent) {
|
||||
int screenOri = Config.getScreenOriMode();
|
||||
if (screenOri != activity.getRequestedOrientation())
|
||||
activity.setRequestedOrientation(screenOri);
|
||||
|
||||
if (updateTranslucent)
|
||||
updateTranslucent(activity);
|
||||
}
|
||||
|
||||
public static SystemBarConfig translucent(
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ListView;
|
||||
|
||||
public class FswListView extends ListView {
|
||||
|
||||
private OnFitSystemWindowsListener mListener;
|
||||
|
||||
public FswListView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public FswListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
public FswListView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void setOnFitSystemWindowsListener(OnFitSystemWindowsListener l) {
|
||||
mListener = l;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean fitSystemWindows(Rect insets) {
|
||||
boolean re = super.fitSystemWindows(insets);
|
||||
if (mListener != null)
|
||||
mListener.onfitSystemWindows(getPaddingLeft(), getPaddingTop(),
|
||||
getPaddingRight(), getPaddingBottom());
|
||||
return re;
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import android.view.View;
|
||||
|
||||
public class FswView extends View {
|
||||
private List<OnFitSystemWindowsListener> mListeners;
|
||||
|
||||
|
||||
public FswView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
@@ -38,17 +38,16 @@ public class FswView extends View {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
public void init() {
|
||||
mListeners = new LinkedList<OnFitSystemWindowsListener>();
|
||||
setFitsSystemWindows(true);
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
public void addOnFitSystemWindowsListener(OnFitSystemWindowsListener l) {
|
||||
mListeners.add(l);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean fitSystemWindows(Rect insets) {
|
||||
boolean re = super.fitSystemWindows(insets);
|
||||
|
||||
@@ -16,41 +16,37 @@
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import com.hippo.ehviewer.ImageLoader;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.util.Log;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.hippo.ehviewer.ImageLoader;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
|
||||
public class LoadImageView extends ImageView {
|
||||
private static final String TAG = "LoadImageView";
|
||||
|
||||
|
||||
public static final int NONE = 0x0;
|
||||
public static final int LOADING = 0x1;
|
||||
public static final int LOADED = 0x2;
|
||||
public static final int FAIL = 0x3;
|
||||
|
||||
|
||||
private static final int WAIT_IMAGE_ID = R.drawable.ic_launcher;
|
||||
private static final int TOUCH_IMAGE_ID = R.drawable.ic_touch;
|
||||
|
||||
|
||||
private static final int DURATION = 300;
|
||||
|
||||
|
||||
private int mState = NONE;
|
||||
|
||||
|
||||
private String mUrl;
|
||||
private String mKey;
|
||||
|
||||
|
||||
public LoadImageView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
@@ -60,18 +56,18 @@ public class LoadImageView extends ImageView {
|
||||
public LoadImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
|
||||
public void setLoadInfo(String url, String key) {
|
||||
mUrl = url;
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
|
||||
public synchronized void setState(int state) {
|
||||
mState = state;
|
||||
if (mState != FAIL)
|
||||
setClickable(false);
|
||||
}
|
||||
|
||||
|
||||
public void setOnClick() {
|
||||
setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -83,40 +79,40 @@ public class LoadImageView extends ImageView {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public String getUrl() {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
|
||||
public synchronized int getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
|
||||
public void setWaitImage() {
|
||||
setImageResource(WAIT_IMAGE_ID);
|
||||
}
|
||||
|
||||
|
||||
public void setTouchImage() {
|
||||
setImageResource(TOUCH_IMAGE_ID);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load target bmp, set progressive animation
|
||||
* @param bmp
|
||||
*/
|
||||
public void setContextImage(Bitmap bmp) {
|
||||
|
||||
|
||||
Drawable[] layers = new Drawable[2];
|
||||
layers[0] = Ui.transparentDrawable;
|
||||
layers[1] = new BitmapDrawable(getContext().getResources(), bmp);
|
||||
TransitionDrawable transitionDrawable = new TransitionDrawable(layers);
|
||||
setImageDrawable(transitionDrawable);
|
||||
transitionDrawable.startTransition(DURATION);
|
||||
|
||||
|
||||
// I get no idea which is better
|
||||
/*
|
||||
setImageBitmap(bmp);
|
||||
@@ -125,37 +121,53 @@ public class LoadImageView extends ImageView {
|
||||
startAnimation(aa);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public static class SimpleImageGetListener
|
||||
implements ImageLoader.OnGetImageListener {
|
||||
private boolean mIsTransitabled = true;
|
||||
private LoadImageView mLiv;
|
||||
|
||||
private boolean mTransitabled = true;
|
||||
private boolean mFixScaleType = false;
|
||||
private final LoadImageView mLiv;
|
||||
|
||||
public SimpleImageGetListener(LoadImageView liv) {
|
||||
mLiv = liv;
|
||||
mLiv.setState(LoadImageView.LOADING);
|
||||
}
|
||||
|
||||
public SimpleImageGetListener setTransitabled(boolean isTransitabled) {
|
||||
mIsTransitabled = isTransitabled;
|
||||
|
||||
public SimpleImageGetListener setTransitabled(boolean transitabled) {
|
||||
mTransitabled = transitabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SimpleImageGetListener setFixScaleType(boolean fixScaleType) {
|
||||
mFixScaleType = fixScaleType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isVaild(String key) {
|
||||
return key.equals(mLiv.getKey())
|
||||
&& mLiv.getParent() != null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onGetImage(String key, Bitmap bmp) {
|
||||
if (isVaild(key) && mLiv.getState() == LoadImageView.LOADING) {
|
||||
if (bmp != null) {
|
||||
if (mIsTransitabled)
|
||||
if (mFixScaleType) {
|
||||
float aspectRatio = (float)bmp.getHeight() / bmp.getWidth();
|
||||
if (aspectRatio < 1.7 && aspectRatio > 1.3)
|
||||
mLiv.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
else
|
||||
mLiv.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
}
|
||||
|
||||
if (mTransitabled)
|
||||
mLiv.setContextImage(bmp);
|
||||
else
|
||||
mLiv.setImageBitmap(bmp);
|
||||
mLiv.setState(LoadImageView.LOADED);
|
||||
} else {
|
||||
if (mFixScaleType)
|
||||
mLiv.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
mLiv.setTouchImage();
|
||||
mLiv.setOnClick();
|
||||
mLiv.setState(LoadImageView.FAIL);
|
||||
|
||||
@@ -16,576 +16,46 @@
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.util.Ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.animation.RotateAnimation;
|
||||
import android.view.animation.Transformation;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class PullListView extends ListView implements AbsListView.OnScrollListener{
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "PullListView";
|
||||
|
||||
private final static int HEADER_PULL_TO_REFRESH = 0;
|
||||
private final static int HEADER_RELEASE_TO_REFRESH = 1;
|
||||
private final static int HEADER_REFRESHING = 2;
|
||||
private final static int HEADER_DONE = 3;
|
||||
private final static int HEADER_CANCEL = 4;
|
||||
|
||||
private final static int FOOTER_REFRESHING = 0;
|
||||
private final static int FOOTER_SUCCESS = 1;
|
||||
private final static int FOOTER_FAIL = 2;
|
||||
|
||||
// arrow animation
|
||||
private RotateAnimation mAnimation;
|
||||
private RotateAnimation mReverseAnimation;
|
||||
|
||||
// Header animation
|
||||
private Animation mRefreshAnimation;
|
||||
private Animation mOverAnimation;
|
||||
|
||||
private LinearLayout mHeader;
|
||||
private LinearLayout mFooter;
|
||||
private TextView mTipTextView;
|
||||
private ImageView mArrowImageView;
|
||||
private ProgressBar mProgressBar;
|
||||
|
||||
private TextView mFooterTipTextView;
|
||||
private ProgressBar mFooterProgressBar;
|
||||
|
||||
// Make sure only one pull event
|
||||
/**
|
||||
* True if Header is shown
|
||||
*/
|
||||
private boolean isHeaderRecored = false;
|
||||
private boolean isFooterRecored = false;
|
||||
|
||||
// Header String to show
|
||||
private String mHeaderPullStr;
|
||||
private String mHeaderReleaseStr;
|
||||
private String mHeaderRefreshStr;
|
||||
private String mHeaderDoneStr;
|
||||
private String mHeaderCancelStr;
|
||||
|
||||
// Footer String to show
|
||||
private String mFooterRefreshStr;
|
||||
private String mFooterSuccessStr;
|
||||
private String mFooterFailStr;
|
||||
|
||||
// Header
|
||||
private int headerHeight;
|
||||
private int headerOriginalLeftPadding;
|
||||
private int headerOriginalTopPadding;
|
||||
private int headerOriginalRightPadding;
|
||||
private int headerOriginalBottomPadding;
|
||||
private int releaseTopPadding;
|
||||
private int doneTopPadding;
|
||||
private int pullThreshold;
|
||||
private int pullOffestMax;
|
||||
|
||||
// Footer
|
||||
private boolean isActionWhenShow = true;
|
||||
|
||||
private int startY;
|
||||
private int headerState = HEADER_DONE;
|
||||
private boolean isBack;
|
||||
|
||||
private int footerState = FOOTER_SUCCESS;
|
||||
|
||||
private OnHeaderRefreshListener headerRefreshListener;
|
||||
private OnFooterRefreshListener footerRefreshListener;
|
||||
|
||||
// To Check scroll to top
|
||||
// Store y of last point
|
||||
private int lastY;
|
||||
|
||||
private boolean mHeaderEnabled = true;
|
||||
@SuppressWarnings("unused")
|
||||
private boolean mFooterEnabled = true;
|
||||
|
||||
public interface OnHeaderRefreshListener {
|
||||
public void onHeaderRefresh();
|
||||
public void onHeaderRefresh(Object obj);
|
||||
}
|
||||
|
||||
public interface OnFooterRefreshListener {
|
||||
public void onFooterRefresh();
|
||||
}
|
||||
|
||||
public class PullListView extends PullViewGroup {
|
||||
|
||||
private ListView mListView;
|
||||
|
||||
public PullListView(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public PullListView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
public PullListView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
// Set arrow animation
|
||||
mAnimation = new RotateAnimation(0, -180,
|
||||
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
|
||||
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
|
||||
mAnimation.setInterpolator(new LinearInterpolator());
|
||||
mAnimation.setDuration(100);
|
||||
mAnimation.setFillAfter(true);
|
||||
|
||||
mReverseAnimation = new RotateAnimation(-180, 0,
|
||||
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
|
||||
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
|
||||
mReverseAnimation.setInterpolator(new LinearInterpolator());
|
||||
mReverseAnimation.setDuration(100);
|
||||
mReverseAnimation.setFillAfter(true);
|
||||
|
||||
// Set header animation
|
||||
mRefreshAnimation = new Animation() {
|
||||
@Override
|
||||
protected void applyTransformation(float interpolatedTime, Transformation t) {
|
||||
mHeader.setPadding(headerOriginalLeftPadding,
|
||||
(int)((1 - interpolatedTime) * releaseTopPadding + (interpolatedTime * headerOriginalTopPadding)),
|
||||
headerOriginalRightPadding, headerOriginalBottomPadding);
|
||||
mHeader.invalidate();
|
||||
}
|
||||
};
|
||||
mRefreshAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
setEnabled(true);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
mRefreshAnimation.setDuration(100);
|
||||
|
||||
mOverAnimation = new Animation() {
|
||||
@Override
|
||||
protected void applyTransformation(float interpolatedTime, Transformation t) {
|
||||
mHeader.setPadding(headerOriginalLeftPadding,
|
||||
(int)((1 - interpolatedTime) * doneTopPadding - (interpolatedTime * headerHeight)),
|
||||
headerOriginalRightPadding, headerOriginalBottomPadding);
|
||||
mHeader.invalidate();
|
||||
}
|
||||
};
|
||||
mOverAnimation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
setEnabled(true);
|
||||
if (headerState == HEADER_CANCEL) {
|
||||
headerState = HEADER_DONE;
|
||||
isHeaderRecored = false;
|
||||
isBack = false;
|
||||
|
||||
|
||||
Log.d(TAG, "cancel animation over");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
mOverAnimation.setDuration(200);
|
||||
|
||||
mFooter = (LinearLayout)LayoutInflater.from(context).inflate(R.layout.pull_list_view_footer, null);
|
||||
mFooter.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
footerRefresh();
|
||||
}
|
||||
});
|
||||
setOnScrollListener(this);
|
||||
addFooterView(mFooter);
|
||||
mFooterTipTextView = (TextView)mFooter.findViewById(R.id.footer_tip_text);
|
||||
mFooterProgressBar = (ProgressBar)mFooter.findViewById(R.id.footer_progressBar);
|
||||
|
||||
mHeader = (LinearLayout)LayoutInflater.from(context).inflate(R.layout.pull_list_view_header, null);
|
||||
addHeaderView(mHeader);
|
||||
mArrowImageView = (ImageView) mHeader.findViewById(R.id.header_arrow_image);
|
||||
mArrowImageView.setMinimumWidth(50);
|
||||
mArrowImageView.setMinimumHeight(50);
|
||||
mProgressBar = (ProgressBar)mHeader.findViewById(R.id.header_progressBar);
|
||||
mTipTextView = (TextView)mHeader.findViewById(R.id.header_tip_text);
|
||||
|
||||
headerOriginalLeftPadding = mHeader.getPaddingLeft();
|
||||
headerOriginalTopPadding = mHeader.getPaddingTop();
|
||||
headerOriginalRightPadding = mHeader.getPaddingRight();
|
||||
headerOriginalBottomPadding = mHeader.getPaddingBottom();
|
||||
|
||||
Ui.measureView(mHeader);
|
||||
headerHeight = mHeader.getMeasuredHeight();
|
||||
pullThreshold = headerHeight;
|
||||
pullOffestMax = (int)(headerHeight * 2.3f);
|
||||
|
||||
mHeader.setPadding(headerOriginalLeftPadding, -headerHeight, headerOriginalRightPadding, headerOriginalBottomPadding);
|
||||
mHeader.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {}
|
||||
|
||||
@Override
|
||||
public void onScroll(AbsListView view, int firstVisibleItem,
|
||||
int visibleItemCount, int totalItemCount) {
|
||||
if (firstVisibleItem + visibleItemCount == totalItemCount
|
||||
&& isActionWhenShow && totalItemCount > 1)
|
||||
footerRefresh();
|
||||
protected AbsListView initContentView(Context context) {
|
||||
return mListView = new ListView(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
|
||||
final int action = event.getAction() & MotionEvent.ACTION_MASK;
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
lastY = (int)event.getY();
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
headerState = HEADER_DONE;
|
||||
isHeaderRecored = false;
|
||||
isBack = false;
|
||||
changeHeaderViewByState();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (headerState == HEADER_PULL_TO_REFRESH) {
|
||||
headerState = HEADER_CANCEL;
|
||||
changeHeaderViewByState();
|
||||
}
|
||||
else if (headerState == HEADER_RELEASE_TO_REFRESH) {
|
||||
headerState = HEADER_REFRESHING;
|
||||
changeHeaderViewByState();
|
||||
onHeaderRefresh();
|
||||
} else if (headerState == HEADER_DONE) {
|
||||
isHeaderRecored = false;
|
||||
isBack = false;
|
||||
changeHeaderViewByState();
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int tempY = (int)event.getY();
|
||||
int FingerOffsetY = tempY - lastY;
|
||||
lastY = tempY;
|
||||
if (mHeaderEnabled && !isHeaderRecored && !isFooterRecored && isListAtTop() && FingerOffsetY > 0) {
|
||||
isHeaderRecored = true;
|
||||
startY = tempY;
|
||||
}
|
||||
|
||||
if (headerState != HEADER_REFRESHING && isHeaderRecored) {
|
||||
int offsetY = getShowOffset(tempY - startY, pullOffestMax);
|
||||
if (headerState == HEADER_RELEASE_TO_REFRESH) {
|
||||
// 往上推,推到屏幕足够掩盖head的程度,但还没有全部掩盖
|
||||
if (offsetY < pullThreshold && offsetY > 0) {
|
||||
headerState = HEADER_PULL_TO_REFRESH;
|
||||
changeHeaderViewByState();
|
||||
}
|
||||
// 一下子推到顶
|
||||
else if (offsetY <= 0) {
|
||||
headerState = HEADER_DONE;
|
||||
startY = tempY;
|
||||
isHeaderRecored = false;
|
||||
}
|
||||
} else if (headerState == HEADER_PULL_TO_REFRESH) {
|
||||
// 下拉到可以进入RELEASE_TO_REFRESH的状态
|
||||
if (offsetY >= pullThreshold) {
|
||||
headerState = HEADER_RELEASE_TO_REFRESH;
|
||||
isBack = true;
|
||||
changeHeaderViewByState();
|
||||
}
|
||||
// 上推到顶了
|
||||
else if (offsetY <= 0) {
|
||||
headerState = HEADER_DONE;
|
||||
startY = tempY;
|
||||
isHeaderRecored = false;
|
||||
}
|
||||
} else if (headerState == HEADER_DONE) {
|
||||
if (offsetY >= 0) {
|
||||
headerState = HEADER_PULL_TO_REFRESH;
|
||||
changeHeaderViewByState();
|
||||
} else {
|
||||
startY = tempY;
|
||||
isHeaderRecored = false;
|
||||
}
|
||||
}
|
||||
|
||||
// update headView
|
||||
if (headerState == HEADER_RELEASE_TO_REFRESH
|
||||
|| headerState == HEADER_PULL_TO_REFRESH) {
|
||||
int topPadding = (int)(offsetY - headerHeight);
|
||||
mHeader.setPadding(headerOriginalLeftPadding, topPadding, headerOriginalRightPadding, headerOriginalBottomPadding);
|
||||
mHeader.invalidate();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (isHeaderRecored && (headerState == HEADER_PULL_TO_REFRESH ||
|
||||
headerState == HEADER_RELEASE_TO_REFRESH)) {
|
||||
event.setAction(MotionEvent.ACTION_CANCEL);
|
||||
|
||||
|
||||
Log.d(TAG, "set cancel");
|
||||
}
|
||||
|
||||
super.onTouchEvent(event);
|
||||
|
||||
Log.d(TAG, "get event");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getShowOffset(int eventOffset, int target) {
|
||||
if (eventOffset == 0) // avoid divide zero
|
||||
return 0;
|
||||
if (eventOffset < 0)
|
||||
return eventOffset;
|
||||
else
|
||||
return (target * eventOffset) / (eventOffset + target);
|
||||
}
|
||||
|
||||
// Refresh header UI
|
||||
private void changeHeaderViewByState() {
|
||||
switch (headerState) {
|
||||
case HEADER_RELEASE_TO_REFRESH:
|
||||
mArrowImageView.setVisibility(View.VISIBLE);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mTipTextView.setVisibility(View.VISIBLE);
|
||||
mArrowImageView.clearAnimation();
|
||||
mArrowImageView.startAnimation(mAnimation);
|
||||
mTipTextView.setText(mHeaderReleaseStr);
|
||||
break;
|
||||
case HEADER_PULL_TO_REFRESH:
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mTipTextView.setVisibility(View.VISIBLE);
|
||||
mArrowImageView.clearAnimation();
|
||||
mArrowImageView.setVisibility(View.VISIBLE);
|
||||
if (isBack) {
|
||||
isBack = false;
|
||||
mArrowImageView.clearAnimation();
|
||||
mArrowImageView.startAnimation(mReverseAnimation);
|
||||
}
|
||||
mTipTextView.setText(mHeaderPullStr);
|
||||
break;
|
||||
case HEADER_REFRESHING:
|
||||
releaseTopPadding = mHeader.getPaddingTop();
|
||||
mHeader.startAnimation(mRefreshAnimation);
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
mArrowImageView.clearAnimation();
|
||||
mArrowImageView.setVisibility(View.GONE);
|
||||
mTipTextView.setText(mHeaderRefreshStr);
|
||||
break;
|
||||
case HEADER_DONE:
|
||||
case HEADER_CANCEL:
|
||||
doneTopPadding = mHeader.getPaddingTop();
|
||||
mHeader.startAnimation(mOverAnimation);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mArrowImageView.setVisibility(View.GONE);
|
||||
mArrowImageView.clearAnimation();
|
||||
// 此处更换图标
|
||||
mArrowImageView.setImageResource(R.drawable.ic_pulltorefresh_arrow);
|
||||
if (headerState == HEADER_DONE)
|
||||
mTipTextView.setText(mHeaderDoneStr);
|
||||
else
|
||||
mTipTextView.setText(mHeaderCancelStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh footer UI
|
||||
private void changeFooterViewByState() {
|
||||
switch (footerState) {
|
||||
case FOOTER_REFRESHING:
|
||||
mFooterTipTextView.setText(mFooterRefreshStr);
|
||||
mFooterProgressBar.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case FOOTER_SUCCESS:
|
||||
mFooterTipTextView.setText(mFooterSuccessStr);
|
||||
mFooterProgressBar.setVisibility(View.GONE);
|
||||
break;
|
||||
case FOOTER_FAIL:
|
||||
mFooterTipTextView.setText(mFooterFailStr);
|
||||
mFooterProgressBar.setVisibility(View.GONE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Header
|
||||
public void setHeaderEnabled(boolean enabled) {
|
||||
mHeaderEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setHeaderString(String pullStr, String releaseStr, String refreshStr, String doneStr, String cancelStr) {
|
||||
mHeaderPullStr = pullStr;
|
||||
mHeaderReleaseStr = releaseStr;
|
||||
mHeaderRefreshStr = refreshStr;
|
||||
mHeaderDoneStr = doneStr;
|
||||
mHeaderCancelStr = cancelStr;
|
||||
|
||||
switch (headerState) {
|
||||
case HEADER_PULL_TO_REFRESH:
|
||||
mTipTextView.setText(mHeaderPullStr);
|
||||
break;
|
||||
case HEADER_RELEASE_TO_REFRESH:
|
||||
mTipTextView.setText(mHeaderReleaseStr);
|
||||
break;
|
||||
case HEADER_REFRESHING:
|
||||
mTipTextView.setText(mHeaderRefreshStr);
|
||||
break;
|
||||
case HEADER_DONE:
|
||||
mTipTextView.setText(mHeaderDoneStr);
|
||||
break;
|
||||
case HEADER_CANCEL:
|
||||
mTipTextView.setText(mHeaderCancelStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean clickHeaderRefresh(Object obj) {
|
||||
if (!mHeaderEnabled || isHeaderRecored || isFooterRecored)
|
||||
return false;
|
||||
|
||||
isHeaderRecored = true;
|
||||
headerState = HEADER_REFRESHING;
|
||||
changeHeaderViewByState();
|
||||
onHeaderRefresh(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setOnRefreshListener(OnHeaderRefreshListener refreshListener) {
|
||||
this.headerRefreshListener = refreshListener;
|
||||
}
|
||||
|
||||
private void onHeaderRefresh() {
|
||||
if (headerRefreshListener != null) {
|
||||
headerRefreshListener.onHeaderRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void onHeaderRefresh(Object obj) {
|
||||
if (headerRefreshListener != null) {
|
||||
headerRefreshListener.onHeaderRefresh(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHeaderRefreshing() {
|
||||
return headerState == HEADER_REFRESHING;
|
||||
}
|
||||
|
||||
public void onHeaderRefreshComplete() {
|
||||
headerState = HEADER_DONE;
|
||||
isHeaderRecored = false;
|
||||
isBack = false;
|
||||
changeHeaderViewByState();
|
||||
}
|
||||
|
||||
// Footer
|
||||
public void setFooterEnabled(boolean enabled) {
|
||||
// TODO Remove footer if false
|
||||
mFooterEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setFooterString(String refreshStr, String successStr, String failStr) {
|
||||
mFooterRefreshStr = refreshStr;
|
||||
mFooterSuccessStr = successStr;
|
||||
mFooterFailStr = failStr;
|
||||
|
||||
switch (footerState) {
|
||||
case FOOTER_REFRESHING:
|
||||
mFooterTipTextView.setText(mFooterRefreshStr);
|
||||
break;
|
||||
case FOOTER_SUCCESS:
|
||||
mFooterTipTextView.setText(mFooterSuccessStr);
|
||||
break;
|
||||
case FOOTER_FAIL:
|
||||
mFooterTipTextView.setText(mFooterFailStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void footerRefresh() {
|
||||
if (!mHeaderEnabled || isHeaderRecored || isFooterRecored)
|
||||
return;
|
||||
|
||||
isFooterRecored = true;
|
||||
footerState = FOOTER_REFRESHING;
|
||||
changeFooterViewByState();
|
||||
|
||||
if (footerRefreshListener != null) {
|
||||
footerRefreshListener.onFooterRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnFooterRefreshListener(OnFooterRefreshListener footerRefreshListener) {
|
||||
this.footerRefreshListener = footerRefreshListener;
|
||||
}
|
||||
|
||||
public void onFooterRefreshComplete(boolean isSuccess) {
|
||||
if (isSuccess) {
|
||||
footerState = FOOTER_SUCCESS;
|
||||
isActionWhenShow = true;
|
||||
}
|
||||
else {
|
||||
footerState = FOOTER_FAIL;
|
||||
isActionWhenShow = false;
|
||||
}
|
||||
isFooterRecored = false;
|
||||
changeFooterViewByState();
|
||||
}
|
||||
|
||||
public boolean isFooterRefreshing() {
|
||||
return footerState == FOOTER_REFRESHING;
|
||||
}
|
||||
|
||||
public void onFooterRefreshComplete(boolean isSuccess, boolean actionWhenShow) {
|
||||
if (isSuccess)
|
||||
footerState = FOOTER_SUCCESS;
|
||||
else
|
||||
footerState = FOOTER_FAIL;
|
||||
isActionWhenShow = actionWhenShow;
|
||||
isFooterRecored = false;
|
||||
changeFooterViewByState();
|
||||
}
|
||||
|
||||
public void setActionWhenShow(boolean actionWhenShow) {
|
||||
isActionWhenShow = actionWhenShow;
|
||||
}
|
||||
|
||||
private boolean isListAtTop() {
|
||||
if(getChildCount() == 0)
|
||||
return true;
|
||||
return getFirstVisiblePosition() == 0
|
||||
&& getChildAt(0).getTop() == getPaddingTop();
|
||||
}
|
||||
|
||||
// Get header width and height
|
||||
|
||||
@Override
|
||||
protected AbsListView initContentView(Context context, AttributeSet attrs) {
|
||||
return mListView = new ListView(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFooterView(View view) {
|
||||
mListView.addFooterView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFooterView(View view) {
|
||||
mListView.removeFooterView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectionFromTop(int position, int y) {
|
||||
mListView.setSelectionFromTop(position, y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.AbsListView;
|
||||
|
||||
import com.etsy.android.grid.StaggeredGridView;
|
||||
|
||||
public class PullStaggeredGridView extends PullViewGroup {
|
||||
|
||||
private StaggeredGridView mStaggeredGridView;
|
||||
|
||||
public PullStaggeredGridView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public PullStaggeredGridView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbsListView initContentView(Context context) {
|
||||
return mStaggeredGridView = new StaggeredGridView(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbsListView initContentView(Context context, AttributeSet attrs) {
|
||||
return mStaggeredGridView = new StaggeredGridView(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFooterView(View view) {
|
||||
mStaggeredGridView.addFooterView(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFooterView(View view) {
|
||||
mStaggeredGridView.removeFooterView(view);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void setSelectionFromTop(int position, int y) {
|
||||
mStaggeredGridView.setSelectionFromTop(position, y);
|
||||
}
|
||||
}
|
||||
+70
-52
@@ -16,64 +16,81 @@
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class HfListView extends SuperSwipeRefreshLayout
|
||||
implements AbsListView.OnScrollListener {
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public abstract class PullViewGroup extends SuperSwipeRefreshLayout
|
||||
implements AbsListView.OnScrollListener{
|
||||
|
||||
private final static int FOOTER_REFRESHING = 0;
|
||||
private final static int FOOTER_SUCCESS = 1;
|
||||
private final static int FOOTER_FAIL = 2;
|
||||
|
||||
private Context mContext;
|
||||
private ListView mListView;
|
||||
|
||||
|
||||
private final Context mContext;
|
||||
private final AbsListView mContentView;
|
||||
|
||||
private View mFooter;
|
||||
private TextView mFooterTipTextView;
|
||||
private ProgressBar mFooterProgressBar;
|
||||
private int footerState = FOOTER_SUCCESS;
|
||||
private OnFooterRefreshListener mFooterRefreshListener;
|
||||
|
||||
|
||||
// Footer String to show
|
||||
private String mFooterRefreshStr;
|
||||
private String mFooterSuccessStr;
|
||||
private String mFooterFailStr;
|
||||
|
||||
|
||||
private boolean mIsEnabledHeader = true;
|
||||
private boolean mIsEnabledFooter = true;
|
||||
|
||||
public HfListView(Context context) {
|
||||
|
||||
public PullViewGroup(Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
mContentView = initContentView(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public HfListView(Context context, AttributeSet attrs) {
|
||||
|
||||
public PullViewGroup(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
mContentView = initContentView(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init content view here
|
||||
* @param context
|
||||
*/
|
||||
protected abstract AbsListView initContentView(Context context);
|
||||
|
||||
/**
|
||||
* Init content view here
|
||||
* @param context
|
||||
*/
|
||||
protected abstract AbsListView initContentView(Context context, AttributeSet attrs);
|
||||
|
||||
protected abstract void addFooterView(View view);
|
||||
|
||||
protected abstract void removeFooterView(View view);
|
||||
|
||||
public abstract void setSelectionFromTop(int position, int y);
|
||||
|
||||
private void init() {
|
||||
mListView = new ListView(mContext);
|
||||
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
addView(mListView, lp);
|
||||
|
||||
mListView.setOnScrollListener(this);
|
||||
mFooter = (LinearLayout)LayoutInflater.from(mContext)
|
||||
addView(mContentView, lp);
|
||||
|
||||
mContentView.setOnScrollListener(this);
|
||||
mFooter = LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.pull_list_view_footer, null);
|
||||
mFooterTipTextView = (TextView)mFooter.findViewById(R.id.footer_tip_text);
|
||||
mFooterProgressBar = (ProgressBar)mFooter.findViewById(R.id.footer_progressBar);
|
||||
@@ -85,39 +102,39 @@ public class HfListView extends SuperSwipeRefreshLayout
|
||||
}
|
||||
});
|
||||
changeFooterViewByState();
|
||||
mListView.addFooterView(mFooter);
|
||||
addFooterView(mFooter);
|
||||
}
|
||||
|
||||
public ListView getListView() {
|
||||
return mListView;
|
||||
|
||||
public AbsListView getContentView() {
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Just a alias
|
||||
* @param l
|
||||
*/
|
||||
public void setOnHeaderRefreshListener(HfListView.OnRefreshListener l) {
|
||||
public void setOnHeaderRefreshListener(OnRefreshListener l) {
|
||||
super.setOnRefreshListener(l);
|
||||
}
|
||||
|
||||
|
||||
public void setOnFooterRefreshListener(OnFooterRefreshListener l) {
|
||||
mFooterRefreshListener = l;
|
||||
}
|
||||
|
||||
|
||||
private void footerRefresh() {
|
||||
if (mFooterRefreshListener.onFooterRefresh()) {
|
||||
footerState = FOOTER_REFRESHING;
|
||||
changeFooterViewByState();
|
||||
|
||||
|
||||
// Disable header refresh
|
||||
if (mIsEnabledHeader)
|
||||
setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set footer UI String
|
||||
*
|
||||
*
|
||||
* @param refreshStr
|
||||
* @param successStr
|
||||
* @param failStr
|
||||
@@ -126,7 +143,7 @@ public class HfListView extends SuperSwipeRefreshLayout
|
||||
mFooterRefreshStr = refreshStr;
|
||||
mFooterSuccessStr = successStr;
|
||||
mFooterFailStr = failStr;
|
||||
|
||||
|
||||
switch (footerState) {
|
||||
case FOOTER_REFRESHING:
|
||||
mFooterTipTextView.setText(mFooterRefreshStr);
|
||||
@@ -139,7 +156,7 @@ public class HfListView extends SuperSwipeRefreshLayout
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Refresh footer UI
|
||||
*/
|
||||
@@ -159,54 +176,55 @@ public class HfListView extends SuperSwipeRefreshLayout
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setHeaderRefreshComplete() {
|
||||
super.setRefreshing(false);
|
||||
}
|
||||
|
||||
|
||||
public void setFooterRefreshComplete(boolean isSuccess) {
|
||||
if (isSuccess)
|
||||
footerState = FOOTER_SUCCESS;
|
||||
else
|
||||
footerState = FOOTER_FAIL;
|
||||
changeFooterViewByState();
|
||||
|
||||
|
||||
// enable header refresh
|
||||
if (mIsEnabledHeader)
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
|
||||
public void setAnyRefreshComplete() {
|
||||
setAnyRefreshComplete(true);
|
||||
}
|
||||
|
||||
|
||||
public void setAnyRefreshComplete(boolean isSuccess) {
|
||||
setHeaderRefreshComplete();
|
||||
setFooterRefreshComplete(isSuccess);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return True if actionbar is refreshing
|
||||
*/
|
||||
public boolean isHeaderRefreshing() {
|
||||
return super.isRefreshing();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return True if footer is refreshing
|
||||
*/
|
||||
public boolean isFooterRefreshing() {
|
||||
return footerState == FOOTER_REFRESHING;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return True if actionbar or footer is refreshing
|
||||
*/
|
||||
@Override
|
||||
public boolean isRefreshing() {
|
||||
return (mIsEnabledHeader ? isHeaderRefreshing() : false)
|
||||
| (mIsEnabledFooter ? isFooterRefreshing() : false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(AbsListView view, int scrollState) {}
|
||||
|
||||
@@ -219,25 +237,25 @@ public class HfListView extends SuperSwipeRefreshLayout
|
||||
&& footerState != FOOTER_FAIL)
|
||||
footerRefresh();
|
||||
}
|
||||
|
||||
|
||||
public void setEnabledHeader(boolean enabled) {
|
||||
if (mIsEnabledHeader == enabled)
|
||||
return;
|
||||
|
||||
|
||||
mIsEnabledHeader = enabled;
|
||||
setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
public void setEnabledFooter(boolean enabled) {
|
||||
if (mIsEnabledFooter == enabled)
|
||||
return;
|
||||
|
||||
|
||||
if (mIsEnabledFooter = enabled)
|
||||
mListView.addFooterView(mFooter);
|
||||
addFooterView(mFooter);
|
||||
else
|
||||
mListView.removeFooterView(mFooter);
|
||||
removeFooterView(mFooter);
|
||||
}
|
||||
|
||||
|
||||
public interface OnFooterRefreshListener {
|
||||
/**
|
||||
* @return True if this refresh action is vaild
|
||||
Reference in new issue
Block a user