添加列表缩略图模式

This commit is contained in:
seven332 committed 2014-07-27 13:17:46 +08:00
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>
+85
View File
@@ -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>
+35
View File
@@ -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
View File
@@ -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>
+15
View File
@@ -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>
+15 -15
View File
@@ -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
+149 -38
View File
@@ -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;
}
}
}
+13 -5
View File
@@ -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;
-8
View File
@@ -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;
}
}
+4 -5
View File
@@ -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);
+25 -555
View File
@@ -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);
}
}
@@ -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