部分改善详情界面,添加 Ripple 效果

This commit is contained in:
seven332 committed 2014-08-04 22:38:31 +08:00
1 parent ee229b11da
commit e08a9bfdfa
96 files changed
+2585 -2139

No files matched your search

+6 -7
View File
@@ -47,7 +47,7 @@
</intent-filter>
</activity>
<activity
android:name="com.hippo.ehviewer.ui.GalleryListActivity"
android:name=".ui.GalleryListActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
@@ -62,9 +62,8 @@
android:resource="@xml/searchable" />
</activity>
<activity
android:name="com.hippo.ehviewer.ui.GalleryDetailActivity"
android:name=".ui.GalleryDetailActivity"
android:configChanges="orientation|screenSize"
android:launchMode="singleTask"
android:screenOrientation="behind"
android:windowSoftInputMode="adjustPan|adjustUnspecified|stateHidden" >
<intent-filter>
@@ -81,19 +80,19 @@
</intent-filter>
</activity>
<activity
android:name="com.hippo.ehviewer.ui.GalleryActivity"
android:name=".ui.GalleryActivity"
android:configChanges="orientation|screenSize"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.hippo.ehviewer.ui.SettingsActivity"
android:name=".ui.SettingsActivity"
android:configChanges="orientation|screenSize"
android:icon="@drawable/ic_action_settings"
android:label="@string/preference_settings_title"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.hippo.ehviewer.ui.FavouriteActivity"
android:name=".ui.FavouriteActivity"
android:configChanges="orientation|screenSize"
android:icon="@drawable/ic_action_favorite"
android:label="@string/favourite"
@@ -101,7 +100,7 @@
android:theme="@style/AppTheme.ListActivity" >
</activity>
<activity
android:name="com.hippo.ehviewer.ui.DownloadActivity"
android:name=".ui.DownloadActivity"
android:configChanges="orientation|screenSize"
android:icon="@drawable/ic_action_download"
android:label="@string/download"
+20
View File
@@ -0,0 +1,20 @@
<?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.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="300" />
+20
View File
@@ -0,0 +1,20 @@
<?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.
-->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="300" />
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

+8 -8
View File
@@ -39,7 +39,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/holo_blue_light" />
android:background="@color/theme_red" />
<Button
android:id="@+id/color_scheme_dialog_preset_two"
@@ -47,7 +47,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/holo_green_light" />
android:background="@color/theme_orange" />
<Button
android:id="@+id/color_scheme_dialog_preset_three"
@@ -55,7 +55,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/holo_orange_dark" />
android:background="@color/theme_lime" />
<Button
android:id="@+id/color_scheme_dialog_preset_four"
@@ -63,7 +63,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/holo_orange_light" />
android:background="@color/theme_green" />
<Button
android:id="@+id/color_scheme_dialog_old_color"
@@ -101,7 +101,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/holo_purple" />
android:background="@color/theme_teal" />
<Button
android:id="@+id/color_scheme_dialog_preset_six"
@@ -109,7 +109,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/holo_red_light" />
android:background="@color/theme_blue" />
<Button
android:id="@+id/color_scheme_dialog_preset_seven"
@@ -117,7 +117,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/darker_gray" />
android:background="@color/theme_purple" />
<Button
android:id="@+id/color_scheme_dialog_preset_eight"
@@ -125,7 +125,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/color_scheme_dialog_row_padding"
android:layout_weight="1"
android:background="@android:color/black" />
android:background="@color/theme_brown" />
<LinearLayout
android:layout_width="0dp"
+2 -2
View File
@@ -81,7 +81,7 @@
<View
android:layout_width="fill_parent"
android:layout_height="1.0dp"
android:background="@color/detail_divider" />
android:background="@color/divider" />
<LinearLayout
android:id="@+id/tags_layout"
@@ -95,7 +95,7 @@
android:id="@+id/divider"
android:layout_width="fill_parent"
android:layout_height="1.0dp"
android:background="@color/detail_divider" />
android:background="@color/divider" />
<include
android:id="@+id/page_list"
+1 -1
View File
@@ -25,7 +25,7 @@
android:layout_width="match_parent"
android:layout_height="0.0dp"
android:layout_weight="1"
android:divider="@color/detail_divider"
android:divider="@color/divider"
android:dividerHeight="1.0dp"
auto:filter="dir" >
</com.hippo.ehviewer.widget.FileExplorerView>
+2 -4
View File
@@ -22,12 +22,10 @@
<com.hippo.ehviewer.widget.FswView
android:id="@+id/alignment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@android:color/transparent"
android:dividerHeight="8dp" />
android:layout_height="match_parent" />
<com.hippo.ehviewer.widget.PullListView
android:id="@+id/list"
android:id="@+id/gallery_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
+3 -3
View File
@@ -45,7 +45,7 @@
<TextView
android:id="@+id/uploader"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/name"
@@ -70,7 +70,7 @@
<TextView
android:id="@+id/category"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
@@ -83,7 +83,7 @@
<TextView
android:id="@+id/posted"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
+1 -1
View File
@@ -20,6 +20,6 @@
android:layout_height="match_parent"
android:background="@android:color/holo_blue_dark"
android:clickable="true"
android:divider="@color/detail_divider"
android:divider="@color/divider"
android:dividerHeight="1.0dp"
android:scrollbarThumbVertical="@drawable/scrollbar_white" />
+303
View File
@@ -0,0 +1,303 @@
<?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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:auto="http://schemas.android.com/apk/res-auto"
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" />
<ScrollView
android:id="@+id/detail_scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clipToPadding="false"
android:visibility="gone" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp" >
<!-- Header -->
<RelativeLayout
android:id="@+id/detail_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" >
<com.hippo.ehviewer.widget.LoadImageView
android:id="@+id/thumb"
android:layout_width="120dp"
android:layout_height="180dp" />
<TextView
android:id="@+id/title"
style="@style/DetailTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_toRightOf="@id/thumb" />
<TextView
android:id="@+id/uploader"
style="@style/DetailSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/title"
android:layout_below="@id/title"
android:layout_marginTop="8dp" />
</RelativeLayout>
<!-- Bottons -->
<LinearLayout
android:id="@+id/detail_buttons"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:visibility="gone" >
<com.hippo.ehviewer.widget.SuperButton
android:id="@+id/download"
style="@style/SuperButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="4dp"
android:layout_weight="1"
android:text="@string/download" />
<com.hippo.ehviewer.widget.SuperButton
android:id="@+id/read"
style="@style/SuperButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_weight="1"
android:text="@string/read"
android:textColor="@color/primary_text_light" />
</LinearLayout>
<!-- Waring text can be shown here -->
<TextView
android:id="@+id/warning"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@color/divider"
android:visibility="gone" />
<!-- Actions -->
<LinearLayout
android:id="@+id/detail_actions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:orientation="horizontal"
android:visibility="gone" >
<TextView
android:id="@+id/category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:drawablePadding="4dp"
android:gravity="center"
android:maxWidth="52dp"
android:textSize="@dimen/text_little_small" />
<TextView
android:id="@+id/more_of_uploader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:drawablePadding="4dp"
android:gravity="center"
android:maxWidth="52dp"
android:text="上传者更多内容"
android:textSize="@dimen/text_little_small" />
<TextView
android:id="@+id/similar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:drawablePadding="4dp"
android:gravity="center"
android:maxWidth="52dp"
android:text="相似内容"
android:textSize="@dimen/text_little_small" />
</LinearLayout>
<View
android:id="@+id/detail_divider_a_m"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@color/divider"
android:visibility="gone" />
<!-- More detail -->
<RelativeLayout
android:id="@+id/detail_more"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:visibility="gone" >
<TextView
android:id="@+id/language"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/posted"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true" />
<TextView
android:id="@+id/pages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/language"
android:layout_marginTop="8dp"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/posted"
android:layout_marginTop="8dp"
android:layout_alignParentRight="true" />
<!-- Theme color -->
<TextView
android:id="@+id/detail_more_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/pages"
android:layout_marginTop="8dp"
android:layout_centerHorizontal="true"
android:text="点击查看更多" />
</RelativeLayout>
<View
android:id="@+id/detail_divider_m_r"
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="@color/divider"
android:visibility="gone" />
<RelativeLayout
android:id="@+id/detail_rate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:visibility="gone" >
<TextSwitcher
android:id="@+id/rating_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:inAnimation="@anim/anim_fade_in"
android:outAnimation="@anim/anim_fade_out" />
<com.hippo.ehviewer.widget.ProgressiveRatingBar
android:id="@+id/rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rating_text"
android:layout_centerHorizontal="true"
android:layout_marginTop="8.0dp"
android:isIndicator="false"
android:numStars="5"
android:stepSize="0.5" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rating"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/favorite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="32dp"
android:gravity="center"
android:maxWidth="52dp"
android:text="@string/favourite"
android:textSize="@dimen/text_little_small" />
<TextView
android:id="@+id/rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="32dp"
android:gravity="center"
android:maxWidth="52dp"
android:text="@string/rate"
android:textSize="@dimen/text_little_small" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>
<ScrollView
android:id="@+id/more_detail_scroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/background_light"
android:clipToPadding="false"
android:visibility="gone" >
<TextView
android:id="@+id/more_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:textIsSelectable="true"
android:textSize="@dimen/text_little_large" />
</ScrollView>
<com.hippo.ehviewer.widget.RefreshTextView
android:id="@+id/refresh_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="12dp"
android:gravity="center"
android:textColor="@android:color/holo_blue_dark"
android:textSize="24sp"
android:visibility="gone" />
</FrameLayout>
+6 -8
View File
@@ -14,33 +14,31 @@
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"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:divider="@android:color/transparent"
android:dividerHeight="8dp" />
android:layout_height="match_parent" />
<com.hippo.ehviewer.widget.PullStaggeredGridView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list"
android:id="@+id/gallery_list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:saveEnabled="false"
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:layout_gravity="center"
android:layout_margin="12dp"
android:gravity="center_horizontal"
android:textColor="@android:color/holo_blue_dark"
android:textSize="24sp" />
</RelativeLayout>
</FrameLayout>
+4 -4
View File
@@ -24,7 +24,7 @@
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"
@@ -38,7 +38,7 @@
<TextView
android:id="@+id/uploader"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/name"
@@ -63,7 +63,7 @@
<TextView
android:id="@+id/category"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
@@ -76,7 +76,7 @@
<TextView
android:id="@+id/posted"
style="@style/CardSubtitle"
style="@style/CardMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
+2 -2
View File
@@ -28,12 +28,12 @@
<TextView
android:id="@+id/category"
style="@style/CardSubtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/thumb"
android:gravity="center"
android:textColor="@android:color/white" />
android:singleLine="true"
android:textColor="@color/primary_text_light" />
<TextView
android:id="@+id/simple_language"
+1 -1
View File
@@ -27,7 +27,7 @@
<View
android:layout_width="fill_parent"
android:layout_height="1.0dp"
android:background="@color/detail_divider" />
android:background="@color/divider" />
<ListView
android:id="@+id/list_menu_item_list"
+1 -1
View File
@@ -24,7 +24,7 @@
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:clickable="true"
android:divider="@color/detail_divider"
android:divider="@color/divider"
android:dividerHeight="1.0dp"
android:scrollbarThumbVertical="@drawable/scrollbar_white" />
+1 -1
View File
@@ -25,7 +25,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="8.0dp"
android:textSize="@dimen/text_xlarge" />
android:textSize="@dimen/text_large" />
<com.hippo.ehviewer.widget.ProgressiveRatingBar
android:id="@+id/rate"
+1 -2
View File
@@ -20,8 +20,7 @@
<com.hippo.ehviewer.widget.FswView
android:id="@+id/alignment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true" />
android:layout_height="match_parent" />
<android.support.v4.view.ViewPager
android:id="@+id/pager"
+2 -2
View File
@@ -358,8 +358,8 @@
<string name="rating4">不行</string>
<string name="rating3">糟糕</string>
<string name="rating2">瞎眼</string>
<string name="rating1">以头抢地</string>
<string name="rating0">感觉快要窒息了</string>
<string name="rating1">快要窒息了</string>
<string name="rating0">…</string>
<!-- Util -->
<string name="invalid_input">无效的输入</string>
+11 -16
View File
@@ -30,7 +30,6 @@
<color name="holo_purple_light_light">#ffd7a2e6</color>
<color name="ab_bg">@android:color/holo_blue_dark</color>
<color name="list_main_bg">#ffe5e5e5</color>
<color name="tag_bg">#bbffffff</color>
<color name="holo_blue_light_light">#ff81d3f7</color>
@@ -49,35 +48,31 @@
<color name="misc_bg">#ffffaaff</color>
<color name="unknown_bg">@android:color/black</color>
<color name="fav0">#ff616161</color>
<color name="fav1">#ffff3e3e</color>
<color name="fav2">#ffff923e</color>
<color name="fav3">#fffff43e</color>
<color name="fav4">#ff3eff6b</color>
<color name="fav5">#ffb1ff3e</color>
<color name="fav6">#ff3efeff</color>
<color name="fav7">#ff4b3eff</color>
<color name="fav8">#ffa23eff</color>
<color name="fav9">#ffff3ec4</color>
<color name="title_primary">#ff333333</color>
<color name="title_secondary">#ffaaaaaa</color>
<color name="detail_title_secondary">#ff777777</color>
<color name="detail_divider">#22000000</color>
<color name="btn_bg_color_default">#ff2196f3</color>
<color name="btn_white_default">#fff0f0f0</color>
<color name="divider">#22000000</color>
<color name="background_light">#fffafafa</color>
<color name="background_dark">#ff212121</color>
<color name="background_little_light">#ffe5e5e5</color>
<color name="primary_text_dark">#de000000</color>
<color name="secondary_text_dark">#8a000000</color>
<color name="primary_text_light">#deffffff</color>
<color name="secondary_text_light">#61ffffff</color>
<color name="theme_red">#ffc53929</color>
<color name="theme_orange">#ffff9100</color>
<color name="theme_lime">#ffafb42b</color>
<color name="theme_green">#ff0b8043</color>
<color name="theme_teal">#ff0097a7</color>
<color name="theme_blue">#ff3367d6</color>
<color name="theme_purple">#ff9c27b0</color>
<color name="theme_brown">#ff795548</color>
</resources>
+9 -4
View File
@@ -28,10 +28,6 @@
<dimen name="tab_text">16.0sp</dimen>
<dimen name="text_xlarge">18.0sp</dimen>
<dimen name="text_large">16.0sp</dimen>
<dimen name="text_medium">13.0sp</dimen>
<dimen name="list_thumb_width">80dp</dimen>
<dimen name="list_thumb_height">120dp</dimen>
@@ -56,4 +52,13 @@
<!-- Color scheme dialog -->
<dimen name="color_scheme_dialog_row_padding">8.0dip</dimen>
<dimen name="text_super_large">20.0sp</dimen>
<dimen name="text_large">18.0sp</dimen>
<dimen name="text_little_large">16.0sp</dimen>
<dimen name="text_medium">14.0sp</dimen>
<dimen name="text_little_small">12.0sp</dimen>
<dimen name="text_small">10.0sp</dimen>
<dimen name="text_super_small">8.0sp</dimen>
</resources>
+33 -23
View File
@@ -45,7 +45,7 @@
<item name="@android:textColorHint">@color/secondary_text_dark</item>
<item name="@android:textColorHighlight">#6640c4ff</item>
<item name="@android:textColorLink">#ff00bcd4</item>
<item name="@android:textSize">14sp</item>
<item name="@android:textSize">@dimen/text_medium</item>
<item name="@android:fontFamily">sans-serif</item>
<item name="@android:textStyle">normal</item>
</style>
@@ -99,38 +99,48 @@
</style>
<!-- Text -->
<style name="CardTitle">
<item name="android:textColor">@color/title_primary</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
<item name="android:singleLine">false</item>
<item name="android:lineSpacingExtra">0.0sp</item>
<style name="TextAppearance.CardTitle">
<item name="android:textSize">@dimen/text_little_large</item>
</style>
<style name="CardSubtitle">
<item name="android:textSize">@dimen/text_medium</item>
<item name="android:textColor">@color/title_secondary</item>
<style name="CardTitle">
<item name="@android:textAppearance">@style/TextAppearance.CardTitle</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
<item name="android:lineSpacingExtra">0sp</item>
</style>
<style name="TextAppearance.CardMessage">
<item name="android:textColor">@color/secondary_text_dark</item>
</style>
<style name="CardMessage">
<item name="@android:textAppearance">@style/TextAppearance.CardMessage</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">1</item>
<item name="android:singleLine">true</item>
<item name="android:drawablePadding">4.0dip</item>
<item name="android:lineSpacingExtra">0.0sp</item>
</style>
<style name="TextAppearance.DetailTitle">
<item name="android:textSize">@dimen/text_large</item>
<item name="android:textColor">@color/primary_text_dark</item>
</style>
<style name="DetailTitle">
<item name="android:textSize">@dimen/detail_title_size</item>
<item name="android:textColor">@color/title_primary</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
<item name="android:singleLine">false</item>
<item name="android:lineSpacingExtra">0.0sp</item>
<item name="@android:textAppearance">@style/TextAppearance.DetailTitle</item>
<item name="@android:maxLines">6</item>
<item name="@android:ellipsize">end</item>
</style>
<style name="TextAppearance.DetailSubtitle">
<item name="android:textSize">@dimen/text_little_large</item>
<item name="android:textColor">@color/secondary_text_dark</item>
</style>
<style name="DetailSubtitle">
<item name="android:textSize">@dimen/detail_subtitle_size</item>
<item name="android:textColor">@color/detail_title_secondary</item>
<item name="android:ellipsize">marquee</item>
<item name="android:singleLine">true</item>
<item name="@android:textAppearance">@style/TextAppearance.DetailSubtitle</item>
<item name="@android:singleLine">true</item>
<item name="@android:ellipsize">marquee</item>
</style>
<style name="TextTag">
+21 -38
View File
@@ -14,67 +14,50 @@
limitations under the License.
-->
<resources>
<!-- Application theme. -->
<style name="AppTheme" parent="@android:Theme.Holo.Light">
<item name="@android:textAppearance">@style/TextAppearance</item>
<item name="@android:windowBackground">@color/background_light</item>
<!-- ActionBar -->
<item name="@android:actionBarStyle">@style/ActionBar</item>
<item name="@android:actionBarTabStyle">@style/ActionBarTabStyle</item>
<item name="@android:actionOverflowButtonStyle">@style/OverFlow</item>
<item name="@android:homeAsUpIndicator">@drawable/ic_ab_back</item>
<item name="@android:windowActionBarOverlay">true</item>
<!-- Button -->
<!-- <item name="@android:buttonStyle">@style/Button.Blue</item> -->
<!-- Scrollbar attributes -->
<item name="@android:scrollbarThumbVertical">@drawable/scrollbar_blue</item>
<!-- List attributes -->
<!-- item name="@android:listDivider">@drawable/list_divider</item -->
<!-- No action bar shadow -->
<!-- item name="android:windowContentOverlay">@drawable/shadow</item -->
<!-- Dialog -->
<!-- item name="@android:dialogTitleDecorLayout">@layout/dialog_title</item -->
<!-- item name="@android:searchViewVoiceIcon">@android:drawable/ic_voice_search_api_holo_light</item -->
<!-- Dialog attributes -->
<!-- AlertDialog attributes -->
<!-- item name="@android:alertDialogStyle">@style/AlertDialogStyle</item -->
</style>
<style name="AppTheme.Normal">
<!-- nop -->
</style>
<style name="AppTheme.Main">
<item name="@android:homeAsUpIndicator">@drawable/ic_navigation_drawer</item>
</style>
<style name="AppTheme.Main.ListActivity">
<item name="android:windowBackground">@color/list_main_bg</item>
<item name="@android:windowBackground">@color/background_little_light</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="@android:windowActionBar">false</item>
<item name="@android:windowNoTitle">true</item>
</style>
<!-- For activity whose main view is list, make background darker to match white list -->
<style name="AppTheme.ListActivity">
<item name="android:windowBackground">@color/list_main_bg</item>
<item name="@android:windowBackground">@color/background_little_light</item>
</style>
<!-- Theme for start activity -->
<style name="AppTheme.NoActionBar.Transparent">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="@android:windowBackground">@android:color/transparent</item>
<item name="@android:colorBackgroundCacheHint">@null</item>
<item name="@android:windowIsTranslucent">true</item>
<item name="@android:windowAnimationStyle">@android:style/Animation</item>
</style>
</resources>
+8 -16
View File
@@ -22,6 +22,7 @@ import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import android.annotation.SuppressLint;
import android.app.Application;
import com.hippo.ehviewer.cache.ImageCache;
@@ -33,12 +34,14 @@ import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.SuperToast;
public class AppContext extends Application implements UncaughtExceptionHandler {
@SuppressWarnings("unused")
private static final String TAG = "AppContext";
private final DateFormat mFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@SuppressLint("SimpleDateFormat")
public static final DateFormat sFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private Thread.UncaughtExceptionHandler mDefaultHandler;
@@ -52,15 +55,16 @@ public class AppContext extends Application implements UncaughtExceptionHandler
// Init everything
mNetworkThreadPool = new ThreadPool(2, 4);
Config.init(this);
Ui.init(this);
Crash.init(this);
mEhClient = new EhClient(this);
EhClient.createInstance(this);
Download.init(this);
Favorite.init(this);
Data.createInstance(this);
SuperToast.setContext(this);
mData = new Data(this);
// Do catch error prepare
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
@@ -75,22 +79,10 @@ public class AppContext extends Application implements UncaughtExceptionHandler
}
}
public EhClient getEhClient() {
return mEhClient;
}
public ThreadPool getNetworkThreadPool() {
return mNetworkThreadPool;
}
public Data getData() {
return mData;
}
public DateFormat getDateFormat() {
return mFormatter;
}
/**
* {@inheritDoc}
*/
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.ehclient.DetailParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.network.HttpHelper;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* Download a gallery
@@ -72,7 +72,7 @@ public class GallerysDownloader implements Runnable {
mGalleryInfo = galleryInfo;
mPageIndex = startIndex;
mDownloadDir = new File(Config.getDownloadPath(),
Util.rightFileName(mGalleryInfo.gid + '-' + mGalleryInfo.title));
Utils.rightFileName(mGalleryInfo.gid + '-' + mGalleryInfo.title));
mDownloadDir.mkdirs();
// TODO What if these is a file with the same name
+3 -3
View File
@@ -22,7 +22,7 @@ import java.net.URLEncoder;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class ListUrls {
@@ -219,7 +219,7 @@ public class ListUrls {
for (int i = 0; i < tag.length; i++)
tag[i] = URLEncoder.encode(tag[i], "UTF-8");
} catch (UnsupportedEncodingException e) {}
url.append(Util.join(tag, '+'));
url.append(Utils.join(tag, '+'));
// Add page
url.append("/").append(page);
@@ -263,7 +263,7 @@ public class ListUrls {
for (int i = 0; i < tag.length; i++)
tag[i] = URLEncoder.encode(tag[i], "UTF-8");
} catch (UnsupportedEncodingException e) {}
url.append(Util.join(tag, '+')).append("&");
url.append(Utils.join(tag, '+')).append("&");
}
// Add page
+2 -2
View File
@@ -38,7 +38,7 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Future;
import com.hippo.ehviewer.util.FutureListener;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
@@ -75,7 +75,7 @@ public class UpdateHelper {
}
public void autoCheckUpdate() {
if (Config.getUpdateDate() < Util.getDate())
if (Config.getUpdateDate() < Utils.getDate())
checkUpdate();
}
+5 -5
View File
@@ -40,7 +40,7 @@ import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* This class holds the memory and disk bitmap caches.
@@ -121,7 +121,7 @@ public final class ImageCache {
* @param cacheParams The cache parameters to initialize the cache
*/
private void init(final Context context) {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -410,7 +410,7 @@ public final class ImageCache {
* cache first
*/
public void flush() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -432,7 +432,7 @@ public final class ImageCache {
* Clears the disk and memory caches
*/
public void clearCaches() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -458,7 +458,7 @@ public final class ImageCache {
* thread.
*/
public void close() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -0,0 +1,44 @@
/*
* 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.data;
public class ApiGalleryDetail extends ApiGalleryInfo {
public int previewSum;
public int previewPerPage;
public PreviewList[] previewLists;
public ApiGalleryDetail() {}
public ApiGalleryDetail(ApiGalleryInfo apiGalleryInfo) {
gid = apiGalleryInfo.gid;
token = apiGalleryInfo.token;
title = apiGalleryInfo.title;
posted = apiGalleryInfo.posted;
category = apiGalleryInfo.category;
thumb = apiGalleryInfo.thumb;
uploader = apiGalleryInfo.uploader;
rating = apiGalleryInfo.rating;
simpleLanguage = apiGalleryInfo.simpleLanguage;
archiver_key = apiGalleryInfo.archiver_key;
title_jpn = apiGalleryInfo.title_jpn;
filecount = apiGalleryInfo.filecount;
filesize = apiGalleryInfo.filesize;
expunged = apiGalleryInfo.expunged;
torrentcount = apiGalleryInfo.torrentcount;
apiTags = apiGalleryInfo.apiTags;
}
}
@@ -17,13 +17,13 @@
package com.hippo.ehviewer.data;
public class ApiGetGalleryInfo extends GalleryInfo{
public class ApiGalleryInfo extends GalleryInfo{
public String archiver_key;
public String title_jpn;
public String filecount;
public long filesize;
public boolean expunged;
public String torrentcount;
public String[] tags;
public String[] apiTags;
}
+10
View File
@@ -83,6 +83,16 @@ public class Data {
private final DBHelper mDBHelper;
private final SQLiteDatabase mDatabase;
private static Data sInstance;
public static void createInstance(Context context) {
sInstance = new Data(context);
}
public static Data getInstance() {
return sInstance;
}
public Data(Context context) {
mContext = context;
mDBHelper = new DBHelper(mContext);
@@ -51,5 +51,6 @@ public class GalleryDetail extends GalleryInfo {
thumb = galleryInfo.thumb;
uploader = galleryInfo.uploader;
rating = galleryInfo.rating;
simpleLanguage = galleryInfo.simpleLanguage;
}
}
@@ -0,0 +1,36 @@
/*
* 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.data;
public class LofiGalleryDetail extends LofiGalleryInfo {
public int previewSum;
public int previewPerPage;
public PreviewList[] previewLists;
public LofiGalleryDetail(LofiGalleryInfo lofiGalleryInfo) {
gid = lofiGalleryInfo.gid;
token = lofiGalleryInfo.token;
title = lofiGalleryInfo.title;
posted = lofiGalleryInfo.posted;
category = lofiGalleryInfo.category;
thumb = lofiGalleryInfo.thumb;
uploader = lofiGalleryInfo.uploader;
rating = lofiGalleryInfo.rating;
simpleLanguage = lofiGalleryInfo.simpleLanguage;
lofiTags = lofiGalleryInfo.lofiTags;
}
}
@@ -0,0 +1,60 @@
/*
* 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.drawable;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
public class OvalDrawable extends Drawable {
private final Paint mPaint;
public OvalDrawable(int color) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(color);
}
@Override
public void draw(Canvas canvas) {
canvas.drawOval(new RectF(this.getBounds()), mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setColor(mPaint.getColor() & 0x00ffffff | (alpha << 24));
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter cf) {
// Not support
}
@Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf();
}
}
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.LargePreviewList;
import com.hippo.ehviewer.data.NormalPreviewList;
import com.hippo.ehviewer.data.PreviewList;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class DetailParser {
@@ -141,9 +141,9 @@ public class DetailParser {
if (m.find()) {
re |= DETAIL;
thumb = Util.htmlUnsescape(m.group(1));
title = Util.htmlUnsescape(m.group(2));
title_jpn = Util.htmlUnsescape(m.group(3));
thumb = Utils.htmlUnsescape(m.group(1));
title = Utils.htmlUnsescape(m.group(2));
title_jpn = Utils.htmlUnsescape(m.group(3));
category = EhClient.getType(m.group(4));
uploader = m.group(5);
posted = m.group(6);
+25 -15
View File
@@ -56,7 +56,7 @@ import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class EhClient {
@@ -92,6 +92,23 @@ public class EhClient {
private final Handler mHandler;
private final EhInfo mInfo;
private static EhClient sInstance;
public static void createInstance(AppContext appContext) {
sInstance = new EhClient(appContext);
}
public static EhClient getInstance() {
return sInstance;
}
public EhClient(AppContext appContext) {
mAppContext = appContext;
mThreadPool = mAppContext.getNetworkThreadPool();
mHandler = AppHandler.getInstance();
mInfo = EhInfo.getInstance(appContext);
}
public static String getUrlHeader() {
return getUrlHeader(Config.getMode());
}
@@ -227,13 +244,6 @@ public class EhClient {
public void onFailure(String eMsg);
}
public EhClient(AppContext appContext) {
mAppContext = appContext;
mThreadPool = mAppContext.getNetworkThreadPool();
mHandler = AppHandler.getInstance();
mInfo = EhInfo.getInstance(appContext);
}
/**
* True if Login
* @return
@@ -351,7 +361,7 @@ public class EhClient {
listener.onGetAvatar(GET_AVATAR_ERROR);
return;
}
String profileUrl = Util.htmlUnsescape(m.group(1));
String profileUrl = Utils.htmlUnsescape(m.group(1));
// Get avatar url
body = hp.get(profileUrl);
if (body == null) {
@@ -775,7 +785,7 @@ public class EhClient {
strs[1] = "last";
else
strs[1] = m.group(2);
strs[2] = Util.htmlUnsescape(m.group(3));
strs[2] = Utils.htmlUnsescape(m.group(3));
} else
eMsg = mAppContext.getString(R.string.em_parser_error);
} else
@@ -965,7 +975,7 @@ public class EhClient {
}
//Create folder
File folder = new File(Config.getDownloadPath() + File.separatorChar + Util.rightFileName(curDownloadInfo.title)); // TODO For title contain invailed char
File folder = new File(Config.getDownloadPath() + File.separatorChar + Utils.rightFileName(curDownloadInfo.title)); // TODO For title contain invailed char
if (!folder.mkdirs() && !folder.isDirectory()) {
listener.onDownloadMangaOver(curDownloadInfo.gid, false);
curDownloadInfo.status = DownloadInfo.FAILED;
@@ -1006,7 +1016,7 @@ public class EhClient {
Log.d(TAG, folder.getPath());
curControlor = imageDownloader.resetData(folder.getPath(),
String.format("%05d", curDownloadInfo.lastStartIndex + 1) + "." + Util.getExtension(imageUrlStr),
String.format("%05d", curDownloadInfo.lastStartIndex + 1) + "." + Utils.getExtension(imageUrlStr),
imageUrlStr);
imageDownloader.run();
@@ -1129,7 +1139,7 @@ public class EhClient {
if (m.find()) {
prePage = m.group(1);
nextPage = m.group(2);
imageUrlStr = Util.htmlUnsescape(m.group(3));
imageUrlStr = Utils.htmlUnsescape(m.group(3));
return true;
}
return false;
@@ -1522,8 +1532,8 @@ public class EhClient {
gi.count = -1;
gi.gid = j.getInt("gid");
gi.token = j.getString("token");
gi.title = Util.htmlUnsescape(j.getString("title"));
gi.posted = mAppContext.getDateFormat().format(Long.parseLong(j.getString("posted")) * 1000);
gi.title = Utils.htmlUnsescape(j.getString("title"));
gi.posted = AppContext.sFormatter.format(Long.parseLong(j.getString("posted")) * 1000);
gi.thumb = j.getString("thumb");
gi.category = getType(j.getString("category"));
gi.uploader = j.getString("uploader");
+3 -3
View File
@@ -32,7 +32,7 @@ import android.graphics.BitmapFactory;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
*
@@ -89,7 +89,7 @@ public class EhInfo {
} catch (FileNotFoundException e) {
return null;
} finally {
Util.closeStreamQuietly(is);
Utils.closeStreamQuietly(is);
}
}
@@ -230,7 +230,7 @@ public class EhInfo {
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
Util.closeStreamQuietly(os);
Utils.closeStreamQuietly(os);
}
}
@@ -22,7 +22,7 @@ import java.util.regex.Pattern;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.data.LofiGalleryInfo;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class ListParser {
@@ -73,8 +73,8 @@ public class ListParser {
} else {
continue;
}
lgi.thumb = Util.htmlUnsescape(m.group(2));
lgi.title = Util.htmlUnsescape(m.group(3));
lgi.thumb = Utils.htmlUnsescape(m.group(2));
lgi.title = Utils.htmlUnsescape(m.group(3));
if (getPostedAndUploader(m.group(4), pau)) {
lgi.posted = pau[0];
lgi.uploader = pau[1];
@@ -147,12 +147,12 @@ public class ListParser {
gi.category = EhClient.getType(m.group(1));
gi.posted = m.group(2);
if (m.group(3) == null) {
gi.thumb = Util.htmlUnsescape("http://"
gi.thumb = Utils.htmlUnsescape("http://"
+ m.group(5).replace('~', '/'));
gi.title = Util.htmlUnsescape(m.group(6));
gi.title = Utils.htmlUnsescape(m.group(6));
} else {
gi.thumb = Util.htmlUnsescape(m.group(3));
gi.title = Util.htmlUnsescape(m.group(4));
gi.thumb = Utils.htmlUnsescape(m.group(3));
gi.title = Utils.htmlUnsescape(m.group(4));
}
Pattern pattern = Pattern
@@ -27,7 +27,7 @@ import com.hippo.ehviewer.util.FutureListener;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -209,7 +209,7 @@ public class ImageSet {
e.printStackTrace();
} finally {
if (fis != null)
Util.closeStreamQuietly(fis);
Utils.closeStreamQuietly(fis);
}
return res;
}
@@ -231,9 +231,9 @@ public class ImageSet {
public boolean getFileForName(String name, ImageData imageData) {
String[] list = mFolder.list();
for (String item : list) {
if(name.equals(Util.getName(item))) {
if(name.equals(Utils.getName(item))) {
imageData.fileName = item;
if (Util.getExtension(item).toLowerCase().equals(GIF_EXTENSION))
if (Utils.getExtension(item).toLowerCase().equals(GIF_EXTENSION))
imageData.type = TYPE_MOVIE;
else
imageData.type = TYPE_BITMAP;
@@ -1,26 +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.network;
public class Constant {
public static final int HTTP_TEMP_REDIRECT = 307;
public static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36";
public static String userAgent = System.getProperty("http.agent", defaultUserAgent);
public static final int DEFAULT_TIMEOUT = 10 * 1000;
public static final int MAX_REDIRECTS = 5;
public static final int BUFFER_SIZE = 4096;
}
+76 -75
View File
@@ -32,24 +32,25 @@ import org.apache.http.conn.ConnectTimeoutException;
import android.content.Context;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.exception.FileException;
import com.hippo.ehviewer.exception.NoSdCardException;
import com.hippo.ehviewer.exception.StopRequestException;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
// TODO 添加检查次磁盘空间
/**
* Thread unsafe
*
*
* @author Hippo
*
*/
public class Downloader implements Runnable {
private static final String TAG = "Downloader";
public static final int NONE = 0x0;
public static final int READY = 0x1;
public static final int CONNECTING = 0x2;
@@ -57,28 +58,28 @@ public class Downloader implements Runnable {
public static final int FAILED = 0x4;
public static final int COMPLETED = 0x5;
public static final int STOPED = 0x6;
private static final int MAX_RETRY = 3;
private Context mContext;
private final Context mContext;
private File mFile;
private File mFolder;
private String mPath;
private String mFileName;
private URL mUrl;
private Controlor mContorlor;
private final Controlor mContorlor;
private int mTotalSize;
// If support Content-Range, start from it
private int mDownloadSize = 0;
private int mRedirectionCount = 0;
private int status = NONE;
private OnDownloadListener mListener;
private Exception mException;
public interface OnDownloadListener {
public void onDownloadStartConnect();
public void onDownloadStartDownload(int totalSize);
@@ -89,81 +90,81 @@ public class Downloader implements Runnable {
*/
public void onDownloadOver(int status, String eMsg);
}
public class Controlor {
private boolean mStop = false;
public synchronized void stop() {
mStop = true;
mStop = true;
}
public synchronized void reset() {
mStop = false;
mStop = false;
}
public synchronized boolean isStop() {
return mStop;
return mStop;
}
}
public Controlor resetData(String path, String fileName, String urlStr) throws MalformedURLException {
mPath = path;
mFileName = fileName;
mUrl = new URL(urlStr);
mException = null;
mDownloadSize = 0;
mRedirectionCount = 0;
status = READY;
mContorlor.reset();
return mContorlor;
}
public void setOnDownloadListener(OnDownloadListener listener) {
mListener = listener;
}
public Downloader(Context context) {
mContext = context;
mContorlor = new Controlor();
}
public String getEMsg() {
if (mException == null)
return mContext.getString(R.string.em_unknown_error);
else if (mException instanceof MalformedURLException)
return mContext.getString(R.string.em_url_format_error);
else if (mException instanceof ConnectTimeoutException ||
mException instanceof SocketTimeoutException)
return mContext.getString(R.string.em_timeout);
else if (mException instanceof UnknownHostException)
return mContext.getString(R.string.em_unknown_host);
else if (mException instanceof SocketException)
return "SocketException : " + mException.getMessage();
else if (mException instanceof NoSdCardException)
return mContext.getString(R.string.em_no_sdcard);
else if (mException instanceof FileException)
return ((FileException)mException).getMessage();
else
return mException.getMessage();
}
@Override
public void run() {
int retryTimes = 0;
if (true) {
boolean checkFolder = false;
try {
initFolder();
checkFolder = true;
@@ -171,7 +172,7 @@ public class Downloader implements Runnable {
mException = e;
e.printStackTrace();
}
while(checkFolder) {
try {
if (mContorlor.isStop())
@@ -193,50 +194,50 @@ public class Downloader implements Runnable {
}
} else
mException = new NoSdCardException();
if (mContorlor.isStop())
status = STOPED;
if (status != COMPLETED && mFile != null)
mFile.delete();
if (mListener != null)
mListener.onDownloadOver(status, getEMsg());
}
public int getStatus() {
return status;
}
private void initFolder() throws Exception {
mFolder = new File(mPath);
if (!mFolder.exists()) {
if (!mFolder.mkdirs())
throw new FileException(FileException.MKDIR_ERROR);
} else if (!mFolder.isDirectory()){
throw new FileException(FileException.NOT_DIR);
}
if (!mFolder.canWrite())
throw new FileException(FileException.CANNOT_WRITE);
}
private void executeDownload() throws Exception {
while (mRedirectionCount++ < Constant.MAX_REDIRECTS) {
while (mRedirectionCount++ < Constants.MAX_REDIRECTS) {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Get file " + mUrl.toString());
status = CONNECTING;
if (mListener != null)
mListener.onDownloadStartConnect();
conn = (HttpURLConnection)mUrl.openConnection();
conn.setInstanceFollowRedirects(false);
conn.addRequestProperty("Range", "bytes=" + mDownloadSize + "-");
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setConnectTimeout(Constants.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constants.DEFAULT_TIMEOUT);
conn.connect();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
@@ -252,7 +253,7 @@ public class Downloader implements Runnable {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case Constant.HTTP_TEMP_REDIRECT:
case Constants.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
mUrl = new URL(mUrl, location);
continue;
@@ -269,16 +270,16 @@ public class Downloader implements Runnable {
}
//throw new RedirectionException();
}
/**
* Get Response Headers Info
*
*
* @param conn
*/
private void processResponseHeaders(HttpURLConnection conn) {
mTotalSize = conn.getContentLength();
//
//
String range;
if ((range = conn.getHeaderField("Content-Range")) != null) { // Support Content-Range
boolean newNum = true;
@@ -311,17 +312,17 @@ public class Downloader implements Runnable {
mDownloadSize = 0;
}
}
/**
* Transfer data from the given connection to the destination file.
*/
private void transferData(HttpURLConnection conn) throws Exception {
InputStream in = null;
RandomAccessFile raf = null;
if (mContorlor.isStop())
throw new StopRequestException();
try {
try {
in = conn.getInputStream();
@@ -342,7 +343,7 @@ public class Downloader implements Runnable {
transferData(in, raf);
} finally {
if (in != null)
Util.closeStreamQuietly(in);
Utils.closeStreamQuietly(in);
if (raf != null)
try {
raf.close();
@@ -351,8 +352,8 @@ public class Downloader implements Runnable {
}
}
}
/**
* Transfer as much data as possible from the HTTP response to the
* destination file.
@@ -360,48 +361,48 @@ public class Downloader implements Runnable {
@SuppressWarnings("unused")
private void transferData(InputStream in, OutputStream out)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
}
writeDataToDestination(data, bytesRead, out);
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
}
}
/**
* Transfer as much data as possible from the HTTP response to the
* destination file.
*/
private void transferData(InputStream in, RandomAccessFile raf)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
}
writeDataToDestination(data, bytesRead, raf);
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
}
}
/**
* Read some data from the HTTP response stream, handling I/O errors.
* @param data buffer to use to read data
@@ -417,8 +418,8 @@ public class Downloader implements Runnable {
throw e;
}
}
/**
* Write a data buffer to the destination file.
* @param data buffer containing the data to write
@@ -435,7 +436,7 @@ public class Downloader implements Runnable {
throw e;
}
}
/**
* Write a data buffer to the destination file.
* @param data buffer containing the data to write
+10 -10
View File
@@ -54,7 +54,7 @@ import com.hippo.ehviewer.exception.StopRequestException;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* It is not thread safe
@@ -191,12 +191,12 @@ public class HttpHelper {
url = rh.getUrl();
Log.d(TAG, "Requst " + url.toString());
boolean isCookiable = isUrlCookiable(url);
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
while (redirectionCount++ < Constants.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constants.userAgent);
conn.setConnectTimeout(Constants.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constants.DEFAULT_TIMEOUT);
// Set cookie if necessary
if (isCookiable)
EhInfo.getInstance(mContext).setCookie(conn, mPreviewMode);
@@ -232,7 +232,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case Constant.HTTP_TEMP_REDIRECT:
case Constants.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
Log.d(TAG, "New location " + location);
mLastUrl = location;
@@ -361,7 +361,7 @@ public class HttpHelper {
else
baos = new ByteArrayOutputStream();
Util.copy(is, baos, Constant.BUFFER_SIZE);
Utils.copy(is, baos, Constants.BUFFER_SIZE);
// Get charset
String charset = null;
@@ -379,8 +379,8 @@ public class HttpHelper {
} catch (Exception e) {
throw e;
} finally {
Util.closeStreamQuietly(is);
Util.closeStreamQuietly(baos);
Utils.closeStreamQuietly(is);
Utils.closeStreamQuietly(baos);
}
return body;
}
@@ -772,7 +772,7 @@ public class HttpHelper {
private void transferData(InputStream in, OutputStream out)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
mReceivedSize = 0;
while (true) {
@@ -36,7 +36,7 @@ import android.widget.LinearLayout;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.ColorPickerView;
import com.hippo.ehviewer.widget.DialogBuilder;
@@ -208,7 +208,7 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
new SuperToast(context, R.string.restart_to_take_effect).show();
new SuperToast(R.string.restart_to_take_effect).show();
int color = getColor() | 0xff000000;
Config.setThemeColor(color);
@@ -251,28 +251,28 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
public void onClick(final View v) {
switch (v.getId()) {
case R.id.color_scheme_dialog_preset_one:
mColorPicker.setColor(getColor(android.R.color.holo_blue_light));
mColorPicker.setColor(getColor(R.color.theme_red));
break;
case R.id.color_scheme_dialog_preset_two:
mColorPicker.setColor(getColor(android.R.color.holo_green_light));
mColorPicker.setColor(getColor(R.color.theme_orange));
break;
case R.id.color_scheme_dialog_preset_three:
mColorPicker.setColor(getColor(android.R.color.holo_orange_dark));
mColorPicker.setColor(getColor(R.color.theme_lime));
break;
case R.id.color_scheme_dialog_preset_four:
mColorPicker.setColor(getColor(android.R.color.holo_orange_light));
mColorPicker.setColor(getColor(R.color.theme_green));
break;
case R.id.color_scheme_dialog_preset_five:
mColorPicker.setColor(getColor(android.R.color.holo_purple));
mColorPicker.setColor(getColor(R.color.theme_teal));
break;
case R.id.color_scheme_dialog_preset_six:
mColorPicker.setColor(getColor(android.R.color.holo_red_light));
mColorPicker.setColor(getColor(R.color.theme_blue));
break;
case R.id.color_scheme_dialog_preset_seven:
mColorPicker.setColor(getColor(android.R.color.darker_gray));
mColorPicker.setColor(getColor(R.color.theme_purple));
break;
case R.id.color_scheme_dialog_preset_eight:
mColorPicker.setColor(getColor(android.R.color.black));
mColorPicker.setColor(getColor(R.color.theme_brown));
break;
case R.id.color_scheme_dialog_old_color:
mColorPicker.setColor(mCurrentColor);
@@ -290,7 +290,7 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
public AlertDialog create() {
AlertDialog dialog = super.create();
dialog.getWindow().setFormat(PixelFormat.RGBA_8888);
Util.removeHardwareAccelerationSupport(mColorPicker);
Utils.removeHardwareAccelerationSupport(mColorPicker);
return dialog;
}
}
@@ -114,7 +114,7 @@ public class NumberOfColumnsPreference extends Preference
throw new Exception();
}
} catch (Exception e) {
new SuperToast(mContext, R.string.invalid_input, SuperToast.ERROR).show();
new SuperToast(R.string.invalid_input, SuperToast.ERROR).show();
}
}
}).create().show();
@@ -16,17 +16,6 @@
package com.hippo.ehviewer.service;
import java.util.HashMap;
import java.util.Map;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.EhClient.DownloadMangaManager;
import com.hippo.ehviewer.ui.DownloadActivity;
import com.hippo.ehviewer.ui.DownloadInfo;
import com.hippo.ehviewer.util.Download;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -36,6 +25,13 @@ import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.EhClient.DownloadMangaManager;
import com.hippo.ehviewer.ui.DownloadActivity;
import com.hippo.ehviewer.ui.DownloadInfo;
import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Log;
public class DownloadService extends Service {
@@ -45,27 +41,27 @@ public class DownloadService extends Service {
public static final String KEY_GID = "gid";
public static final String KEY_INDEX = "index";
public static final String KEY_STATE = "state";
private AppContext mAppContext;
private ServiceBinder mBinder = null;
private NotificationManager mNotifyManager;
private DownloadMangaManager downloadMangaManager;
@Override
public void onCreate() {
@Override
public void onCreate() {
super.onCreate();
mAppContext = (AppContext)getApplication();
mBinder = new ServiceBinder();
mNotifyManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
downloadMangaManager = mAppContext.getEhClient().new DownloadMangaManager();
downloadMangaManager = EhClient.getInstance().new DownloadMangaManager();
downloadMangaManager.setDownloadService(this);
downloadMangaManager.setOnDownloadMangaListener(new EhClient.OnDownloadMangaListener() {
@Override
@@ -77,13 +73,13 @@ public class DownloadService extends Service {
.setProgress(0, 0, true).setOngoing(true).setAutoCancel(false);
mNotifyManager.notify(DOWNLOAD_NOTIFY_ID, builder.getNotification());
}
@Override
public void onDownloadMangaAllOver() {
mNotifyManager.cancel(DOWNLOAD_NOTIFY_ID);
stopSelf();
}
@Override
public void onDownloadMangaStart(String id) {
DownloadInfo di = Download.get(id);
@@ -99,7 +95,7 @@ public class DownloadService extends Service {
mNotifyManager.notify(DOWNLOAD_NOTIFY_ID, builder.getNotification());
}
}
@Override
public void onDownloadMangaStart(String id, int pageSum, int startIndex) {
DownloadInfo di = Download.get(id);
@@ -117,13 +113,13 @@ public class DownloadService extends Service {
mNotifyManager.cancel(Integer.parseInt(id));
}
}
@Override
public void onDownloadMangaStop(String id) {
// TODO Auto-generated method stub
}
@Override
public void onDownloadMangaOver(String id, boolean ok) {
String mesg = null;
@@ -140,7 +136,7 @@ public class DownloadService extends Service {
builder.setContentText(null).setProgress(0, 0, false).setOngoing(false);
mNotifyManager.notify(Integer.parseInt(id), builder.getNotification());
}
@Override
public void onDownloadPage(String id, int pageSum, int index) {
DownloadInfo di = Download.get(id);
@@ -162,45 +158,45 @@ public class DownloadService extends Service {
public void onDownloadPageProgress(String id, int pageSum,
int index, float totalSize, float downloadSize) {
// TODO Auto-generated method stub
}
});
}
private void setNotification(Notification.Builder builder) {
builder.setSmallIcon(R.drawable.ic_launcher);
Intent intent = new Intent(DownloadService.this,DownloadActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
Intent intent = new Intent(DownloadService.this,DownloadActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
}
@Override
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
return START_NOT_STICKY;
}
@Override
return START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "Service onBind");
return mBinder;
}
@Override
public void onDestroy() {
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service onDestroy");
mNotifyManager.cancel(DOWNLOAD_NOTIFY_ID);
mBinder = null;
mNotifyManager = null;
}
public void add(String gid, String thumb, String detailUrlStr, String title) {
DownloadInfo di = Download.get(gid);
if (di == null) {
@@ -216,7 +212,7 @@ public class DownloadService extends Service {
}
add(di);
}
public void add(String gid, String thumb, String detailUrlStr,
String pageUrlStr, int pageSum, int lastStartIndex, String title) {
DownloadInfo di = Download.get(gid);
@@ -236,7 +232,7 @@ public class DownloadService extends Service {
}
add(di);
}
public void add(DownloadInfo di) {
if (di.status == DownloadInfo.DOWNLOADING
|| di.status == DownloadInfo.WAITING)
@@ -244,16 +240,16 @@ public class DownloadService extends Service {
di.status = DownloadInfo.WAITING;
downloadMangaManager.add(di);
}
public void cancel(String id) {
downloadMangaManager.cancel(id);
}
public void notifyUpdate(){
Intent it = new Intent(ACTION_UPDATE);
sendBroadcast(it);
}
public void notifyUpdate(String gid, int index, int state){
Intent it = new Intent(ACTION_UPDATE);
it.putExtra(KEY_GID, gid);
@@ -261,7 +257,7 @@ public class DownloadService extends Service {
it.putExtra(KEY_STATE, state);
sendBroadcast(it);
}
public class ServiceBinder extends Binder{
public DownloadService getService(){
return DownloadService.this;
@@ -17,35 +17,54 @@
package com.hippo.ehviewer.ui;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import com.google.analytics.tracking.android.EasyTracker;
import com.hippo.ehviewer.cache.ImageCache;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
public abstract class AbstractActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Ui.updateTranslucent(this);
}
@Override
protected void onResume() {
super.onResume();
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onStart() {
protected void onStart() {
super.onStart();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStart(this);
Ui.adjustOrientation(this);
}
@Override
public void onStop() {
protected void onStop() {
super.onStop();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStop(this);
ImageCache.getInstance(this).flush();
}
}
@@ -1,70 +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.ui;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.analytics.tracking.android.EasyTracker;
import com.hippo.ehviewer.cache.ImageCache;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
public abstract class AbstractFragmentActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Ui.updateTranslucent(this);
}
@Override
protected void onResume() {
super.onResume();
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onStart() {
super.onStart();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStart(this);
}
@Override
public void onStop() {
super.onStop();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStop(this);
ImageCache.getInstance(this).flush();
}
}
@@ -35,7 +35,6 @@ import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.ListParser;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.PullViewGroup;
import com.hippo.ehviewer.widget.RefreshTextView;
import com.hippo.ehviewer.widget.SuperToast;
@@ -253,19 +252,19 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
setContentView(getLayoutRes());
mAppContext = (AppContext)getApplication();
mClient = mAppContext.getEhClient();
mClient = EhClient.getInstance();
mGiList = new ArrayList<GalleryInfo>();
mMainView = (RelativeLayout)findViewById(R.id.main);
mPullViewGroup = (PullViewGroup)findViewById(R.id.list);
mPullViewGroup = (PullViewGroup)findViewById(R.id.gallery_list);
mPullViewGroup.setAgainstToChildPadding(true);
mContentView = mPullViewGroup.getContentView();
mRefreshTextView = (RefreshTextView)findViewById(R.id.refresh_text);
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(
new OnFitSystemWindowsListener() {
new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -502,7 +501,7 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
default:
mRefreshTextView.setRefreshing(false);
mRefreshTextView.setVisibility(View.GONE);
new SuperToast(AbstractGalleryActivity.this, eMsg, SuperToast.ERROR).show();
new SuperToast(eMsg, SuperToast.ERROR).show();
}
mPullViewGroup.setAnyRefreshComplete(false);
}
@@ -1,223 +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.ui;
import java.util.List;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LinkifyTextView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.SuperToast;
public class CommentsSectionFragment extends Fragment
implements AdapterView.OnItemLongClickListener, AdapterView.OnItemClickListener {
@SuppressWarnings("unused")
private static final String TAG = "CommentsSectionFragment";
private GalleryDetailActivity mActivity;
private View mRootView;
private ListView mList;
private View mWaitView;
private View mRefreshButton;
private List<Comment> mComments;
private final BaseAdapter adapter = new CommentsAdapter();
private AlertDialog mLongClickDialog;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mActivity = (GalleryDetailActivity)getActivity();
mRootView = inflater.inflate(
R.layout.comments, container, false);
mList = (ListView)mRootView.findViewById(R.id.commtens_list);
mWaitView = mRootView.findViewById(R.id.commtens_wait);
mRefreshButton = mRootView.findViewById(R.id.commtens_refresh);
//mRefreshButton.setOnClickListener(this);
FswView align = (FswView)mActivity.findViewById(R.id.alignment);
int paddingLeft = align.getPaddingLeft();
int paddingTop = align.getPaddingTop();
int paddingRight = align.getPaddingRight();
int paddingBottom = align.getPaddingBottom();
if (paddingTop != 0 || paddingBottom != 0) {
mList.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
align.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mList.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
});
mList.setAdapter(adapter);
mList.setOnItemClickListener(this);
mList.setOnItemLongClickListener(this);
mComments = mActivity.getComments();
if (mComments != null) {
adapter.notifyDataSetChanged();
mWaitView.setVisibility(View.GONE);
}
return mRootView;
}
public void setComments(List<Comment> comments) {
mComments = comments;
adapter.notifyDataSetChanged();
if (mWaitView != null)
mWaitView.setVisibility(View.GONE);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Handler url here
LinkifyTextView comment = ((LinkifyTextView)view.findViewById(R.id.comment));
String url = comment.getTouchedUrl();
if (url != null) {
comment.clearTouchedUrl();
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
final Comment c = (Comment)parent.getItemAtPosition(position);
mLongClickDialog = new DialogBuilder(mActivity)
.setTitle(R.string.what_to_do).setItems(R.array.comment_long_click,
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mLongClickDialog.dismiss();
switch (position) {
case 0:
ClipboardManager cm = (ClipboardManager)mActivity
.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText(null, c.comment));
new SuperToast(mActivity).setMessage(R.string.copyed).show();
break;
case 1:
mActivity.finish();
Intent intent = new Intent(mActivity, GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE, ListUrls.MODE_UPLOADER);
intent.putExtra(GalleryListActivity.KEY_UPLOADER, c.user);
startActivity(intent);
break;
}
}
}).setNegativeButton(android.R.string.cancel,
new View.OnClickListener() {
@Override
public void onClick(View v) {
mLongClickDialog.dismiss();
}
}).create();
mLongClickDialog.show();
return true;
}
private class CommentsAdapter extends BaseAdapter {
@Override
public int getCount() {
if (mComments == null)
return 0;
else
return mComments.size();
}
@Override
public Object getItem(int position) {
return mComments.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
boolean isUserSame = true;
boolean isTimeSame = true;
if (convertView == null) {
convertView = LayoutInflater.from(mActivity)
.inflate(R.layout.comments_item, null);
}
Comment c = mComments.get(position);
TextView user = (TextView)convertView.findViewById(R.id.user);
if (!c.user.equals(user.getText())) {
isUserSame = false;
user.setText(c.user);
}
TextView time = (TextView)convertView.findViewById(R.id.time);
if (!c.time.equals(time.getText())) {
isTimeSame = false;
time.setText(c.time);
}
// No one can post one comment at same this time
if (!isUserSame || !isTimeSame) {
TextView comment = ((TextView)convertView.findViewById(R.id.comment));
comment.setText(Html.fromHtml(c.comment));
}
return convertView;
}
}
}
@@ -1,862 +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.ui;
import java.util.AbstractMap.SimpleEntry;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.ScrollView;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.ImageLoader;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.Data;
import com.hippo.ehviewer.data.GalleryDetail;
import com.hippo.ehviewer.data.PreviewList;
import com.hippo.ehviewer.ehclient.DetailParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.AutoWrapLayout;
import com.hippo.ehviewer.widget.ButtonsDialogBuilder;
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.ProgressiveRatingBar;
import com.hippo.ehviewer.widget.SimpleGridLayout;
import com.hippo.ehviewer.widget.SuperToast;
public class DetailSectionFragment extends Fragment
implements View.OnClickListener, PreviewList.PreviewHolder,
View.OnLayoutChangeListener, ViewSwitcher.ViewFactory {
private static final String TAG = DetailSectionFragment.class.getSimpleName();
private AppContext mAppContext;
private GalleryDetailActivity mActivity;
private EhClient mClient;
private Data mData;
private GalleryDetail mGalleryDetail;
private String mUrl;
private View mRootView;
private ScrollView mScrollView;
private ViewGroup mHeaderView;
private LoadImageView mThumb;
private TextView mTitle;
private TextView mUploader;
private TextView mCategory;
private Button mReadButton;
private Button mRateButton;
private View mColorfulBar;
private ProgressBar mWaitPb;
private Button mRefreshButton;
private ViewGroup mNormalView;
private ViewGroup mOffensiveView;
private ViewGroup mPiningView;
private ViewGroup mPreviewListMain;
private SimpleGridLayout mPreviewListLayout;
private ProgressBar mWaitPreviewList;
private Button mPreviewRefreshButton;
private View mBottomPanel;
private TextView mPreviewNumText;
private View mCancelButton;
private View mOnceButton;
private View mEveryButton;
private View mBackButton;
private View mFrontButton;
private View mKnownButton;
private View mDivider;
private AlertDialog mGoToDialog;
private AlertDialog mTagDialog;
private int mCurPage;
private boolean mShowPreview = false;
private boolean isSetViewFactory = false;
private ShapeDrawable getArrowShapeDrawable(int color, boolean isToLeft) {
Path path = new Path();
if (isToLeft) {
path.moveTo(50, 0);
path.lineTo(50, 100);
path.lineTo(0, 50);
path.close();
} else {
path.moveTo(0, 0);
path.lineTo(0, 100);
path.lineTo(50, 50);
path.close();
}
ShapeDrawable d = new ShapeDrawable(new PathShape(path, 50, 100));
d.getPaint().setColor(color);
return d;
}
private StateListDrawable getArrowClickDrawable(int color, boolean isToLeft) {
StateListDrawable sld = new StateListDrawable();
ShapeDrawable normal = getArrowShapeDrawable(color, isToLeft);
ShapeDrawable grey = getArrowShapeDrawable(Theme.GREY_COLOR, isToLeft);
ShapeDrawable dark = getArrowShapeDrawable(Theme.getDarkerColor(color), isToLeft);
sld.addState(new int[]{-android.R.attr.state_enabled}, grey);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_selected}, dark);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, dark);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, dark);
sld.addState(new int[]{}, normal);
return sld;
}
@Override
public int getCurPreviewPage() {
return mCurPage;
}
@Override
public void onGetPreviewImageFailure() {
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.VISIBLE);
}
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (mShowPreview) {
mShowPreview = false;
mScrollView.smoothScrollTo(0,
mNormalView.getTop() + mDivider.getTop());
}
}
@SuppressLint("InflateParams")
@Override
public View makeView() {
LayoutInflater inflater = LayoutInflater.from(mActivity);
return inflater.inflate(R.layout.detail_avg_text, null);
}
public void handleDetail(GalleryDetail gd) {
mGalleryDetail = gd;
mUrl = mClient.getDetailUrl(
mGalleryDetail.gid, mGalleryDetail.token);
mThumb.setImageDrawable(null);
if (mGalleryDetail.thumb != null) {
mThumb.setLoadInfo(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid));
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryDetail.title);
mUploader.setText(mGalleryDetail.uploader);
mCategory.setText(Ui.getCategoryText(mGalleryDetail.category));
mCategory.setBackgroundColor(Ui.getCategoryColor(mGalleryDetail.category));
// Disable them for temp
mReadButton.setEnabled(false);
mRateButton.setEnabled(false);
} else {
mHeaderView.setVisibility(View.GONE);
mColorfulBar.setVisibility(View.GONE);
mThumb.setLoadInfo(null, null);
}
if (mGalleryDetail.size == null) {
mRefreshButton.setVisibility(View.GONE);
mWaitPb.setVisibility(View.VISIBLE);
mNormalView.setVisibility(View.GONE);
mOffensiveView.setVisibility(View.GONE);
mPiningView.setVisibility(View.GONE);
mClient.getGDetail(mUrl, mGalleryDetail, new GDetailGetListener());
} else {
mRefreshButton.setVisibility(View.GONE);
mWaitPb.setVisibility(View.GONE);
mNormalView.setVisibility(View.VISIBLE);
mOffensiveView.setVisibility(View.GONE);
mPiningView.setVisibility(View.GONE);
layout(mGalleryDetail);
}
/*
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new ImageLoader.OnGetImageListener() {
@Override
public void onGetImage(String key, Bitmap bmp) {
mClient.getGListFromImageSearch(bmp, EhClient.IMAGE_SEARCH_USE_SIMILARITY_SCAN,
null, new EhClient.OnGetGListListener() {
@Override
public void onSuccess(Object checkFlag, List<GalleryInfo> giList,
int maxPage) {
Log.d(TAG, "giList.size() = " + giList.size());
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
Log.d(TAG, eMsg);
}
});
}
});*/
}
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mActivity = (GalleryDetailActivity)getActivity();
mAppContext = (AppContext)mActivity.getApplication();
mClient = mAppContext.getEhClient();
mData = mAppContext.getData();
mRootView = inflater.inflate(
R.layout.detail, container, false);
mScrollView = (ScrollView)mRootView.findViewById(R.id.manga_detail_scrollview);
mHeaderView = (ViewGroup)mRootView.findViewById(R.id.detail_header);
mThumb = (LoadImageView)mHeaderView.findViewById(R.id.detail_cover);
mTitle = (TextView)mHeaderView.findViewById(R.id.detail_title);
mUploader = (TextView)mHeaderView.findViewById(R.id.detail_uploader);
mCategory = (TextView)mHeaderView.findViewById(R.id.detail_category);
mReadButton = (Button)mHeaderView.findViewById(R.id.detail_read);
mRateButton = (Button)mHeaderView.findViewById(R.id.detail_do_rate);
mColorfulBar = mRootView.findViewById(R.id.colorful_bar);
mWaitPb = (ProgressBar)mRootView.findViewById(R.id.detail_wait);
mRefreshButton = (Button)mRootView.findViewById(R.id.detail_refresh);
mNormalView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_normal);
mOffensiveView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_offensive);
mPiningView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_pining);
mPreviewListMain = (ViewGroup)mRootView.findViewById(R.id.page_list);
mPreviewListLayout = (SimpleGridLayout)mRootView.findViewById(R.id.preview_list_layout);
mWaitPreviewList = (ProgressBar)mRootView.findViewById(R.id.paper_list_wait);
mPreviewRefreshButton = (Button)mRootView.findViewById(R.id.preview_button_refresh);
mBottomPanel = mRootView.findViewById(R.id.bottom_panel);
mPreviewNumText = (TextView)mBottomPanel.findViewById(R.id.preview_num);
mCancelButton = mOffensiveView.findViewById(R.id.detail_button_cancel);
mOnceButton = mOffensiveView.findViewById(R.id.detail_button_once);
mEveryButton = mOffensiveView.findViewById(R.id.detail_button_every);
mKnownButton = mPiningView.findViewById(R.id.detail_button_known);
mBackButton = mPreviewListMain.findViewById(R.id.back);
mFrontButton = mPreviewListMain.findViewById(R.id.front);
mDivider = mNormalView.findViewById(R.id.divider);
boolean isRandomColor = Config.getRandomThemeColor();
int color = Config.getThemeColor();
// Set random color
if (isRandomColor)
color = Theme.getRandomDarkColor();
mReadButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mRateButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
if (isRandomColor)
color = Theme.getRandomDarkColor();
mColorfulBar.setBackgroundColor(color);
if (isRandomColor)
color = Theme.getRandomDarkColor();
mRefreshButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mCancelButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mOnceButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mEveryButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mKnownButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
if (isRandomColor)
color = Theme.getRandomDarkColor();
mPreviewNumText.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mBackButton.setBackgroundDrawable(getArrowClickDrawable(color, true));
mFrontButton.setBackgroundDrawable(getArrowClickDrawable(color, false));
mUploader.setOnClickListener(this);
mRefreshButton.setOnClickListener(this);
FswView align = (FswView)mActivity.findViewById(R.id.alignment);
int paddingLeft = align.getPaddingLeft();
int paddingTop = align.getPaddingTop();
int paddingRight = align.getPaddingRight();
int paddingBottom = align.getPaddingBottom();
if (paddingTop != 0 || paddingBottom != 0) {
mScrollView.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
align.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mScrollView.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
});
mScrollView.addOnLayoutChangeListener(this);
mPreviewListLayout.setColumnCountPortrait(
Config.getPreviewColumnsPortrait());
mPreviewListLayout.setColumnCountLandscape(
Config.getPreviewColumnsLandscape());
// Load first detail
mActivity.loadDetail();
return mRootView;
}
private void refreshPageList() {
mPreviewListLayout.removeAllViews();
mPreviewNumText.setText(String.format("%d / %d",
mCurPage+1, mGalleryDetail.previewSum));
PreviewList pageList = mGalleryDetail.previewLists[mCurPage];
if (pageList == null) {
// Update layout
mWaitPreviewList.setVisibility(View.VISIBLE);
mPreviewRefreshButton.setVisibility(View.GONE);
mUrl = mClient.getDetailUrl(
mGalleryDetail.gid, mGalleryDetail.token, mCurPage);
mClient.getPreviewList(mUrl, mCurPage,
new EhClient.OnGetPreviewListListener() {
@Override
public void onSuccess(Object checkFlag, PreviewList pageList) {
if (mActivity.isFinishing())
return;
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.GONE);
int page = (Integer)checkFlag;
mGalleryDetail.previewLists[page] = pageList;
mGalleryDetail.previewLists[page].setData(DetailSectionFragment.this, mActivity, mGalleryDetail, page);
mGalleryDetail.previewLists[page].addPreview(mPreviewListLayout);
mShowPreview = true;
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
if (mActivity.isFinishing())
return;
int page = (Integer)checkFlag;
if (page == mCurPage) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(eMsg)
.show();
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.VISIBLE);
}
}
});
} else {
// Update layout
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.GONE);
mGalleryDetail.previewLists[mCurPage].addPreview(mPreviewListLayout);
mShowPreview = true;
}
}
private AlertDialog createGoToDialog() {
return new DialogBuilder(mActivity).setTitle(R.string.jump)
.setAdapter(new BaseAdapter() {
@Override
public int getCount() {
return mGalleryDetail.previewSum;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@SuppressLint({ "ViewHolder", "InflateParams" })
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
LayoutInflater inflater = mActivity.getLayoutInflater();
View view = inflater.inflate(R.layout.list_item_text, null);
TextView tv = (TextView)view.findViewById(android.R.id.text1);
tv.setText(String.format(getString(R.string.some_page), position + 1));
return tv;
}
}, new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
mGoToDialog.dismiss();
if (position != mCurPage) {
mCurPage = position;
refreshPageList();
}
}
}).setNegativeButton(android.R.string.cancel, new View.OnClickListener() {
@Override
public void onClick(View paramView) {
mGoToDialog.dismiss();
}
}).create();
}
@SuppressWarnings("deprecation")
private void addTags() {
LinearLayout tagsLayout = (LinearLayout)mRootView.findViewById(R.id.tags_layout);
LinkedHashMap<String, LinkedList<SimpleEntry<String, Integer>>> tagGroups =
mGalleryDetail.tags;
tagsLayout.removeAllViews();
int x = Ui.dp2pix(4);
int y = Ui.dp2pix(4);
Resources resources = getResources();
// color
boolean isRandomColor = Config.getRandomThemeColor();
int color = Config.getThemeColor();
// Get tag view resources
int tagTextSize = resources.getDimensionPixelOffset(R.dimen.button_small_size);
ColorStateList tagTextColor = resources.getColorStateList(R.color.blue_bn_text);
int tagPaddingX = resources.getDimensionPixelOffset(R.dimen.button_tag_padding_x);
int tagPaddingY = resources.getDimensionPixelOffset(R.dimen.button_tag_padding_y);
for (Entry<String, LinkedList<SimpleEntry<String, Integer>>> tagGroup : tagGroups.entrySet()) {
LinearLayout tagGroupLayout = new LinearLayout(mActivity);
tagGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
AutoWrapLayout tagLayout = new AutoWrapLayout(mActivity);
// Group name
final String groupName = tagGroup.getKey();
TextView groupNameView = new TextView(new ContextThemeWrapper(mActivity, R.style.TextTag));
groupNameView.setText(groupName);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(x, y, x, y);
tagGroupLayout.addView(groupNameView, lp);
// tags
// get random color
if (isRandomColor)
color = Theme.getRandomDarkColor();
for (SimpleEntry<String, Integer> tag : tagGroup.getValue()) {
final String tagText = tag.getKey();
Button tagView = new Button(mActivity);
tagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tagTextSize);
tagView.setText(tagText);
tagView.setTextColor(tagTextColor);
tagView.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
tagView.setPadding(tagPaddingX, tagPaddingY, tagPaddingX, tagPaddingY);
tagView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AlertButton voteUp = new AlertButton(mActivity);
voteUp.setText(getString(R.string.vote_up));
voteUp.setOnClickListener(new SimpleVote(groupName, tagText, true));
AlertButton voteDown = new AlertButton(mActivity);
voteDown.setText(getString(R.string.vote_down));
voteDown.setOnClickListener(new SimpleVote(groupName, tagText, false));
AlertButton showTagged = new AlertButton(mActivity);
showTagged.setText(getString(R.string.show_tagged));
showTagged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTagDialog.dismiss();
mActivity.finish();
Intent intent = new Intent(mActivity,GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE,
ListUrls.MODE_TAG);
intent.putExtra(GalleryListActivity.KEY_TAG, groupName + ":" + tagText);
startActivity(intent);
}
});
mTagDialog = new ButtonsDialogBuilder(mActivity).setTitle(tagText)
.addButton(voteUp).addButton(voteDown).addButton(showTagged)
.create();
mTagDialog.show();
}
});
AutoWrapLayout.LayoutParams alp = new AutoWrapLayout.LayoutParams();
alp.setMargins(x, y, x, y);
tagLayout.addView(tagView, alp);
}
tagGroupLayout.addView(tagLayout);
tagsLayout.addView(tagGroupLayout);
}
// Add tag
if (isRandomColor)
color = Theme.getRandomDarkColor();
Button addtagView = new Button(mActivity);
addtagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tagTextSize);
addtagView.setText("+");
addtagView.setTextColor(tagTextColor);
addtagView.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
addtagView.setPadding(tagPaddingX, tagPaddingY, tagPaddingX, tagPaddingY);
addtagView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO
new SuperToast(mActivity)
.setMessage(R.string.unfinished)
.show();
}
});
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.RIGHT;
lp.setMargins(x, y, x, y);
tagsLayout.addView(addtagView, lp);
}
private void layout(GalleryDetail md) {
if (mActivity.isFinishing())
return;
// Delete progress bar
mWaitPb.setVisibility(View.GONE);
// Check offensive or not
if (md.firstPage.equals("offensive")) {
mOffensiveView.setVisibility(View.VISIBLE);
mCancelButton.setOnClickListener(this);
mOnceButton.setOnClickListener(this);
mEveryButton.setOnClickListener(this);
}
// Check pining or not
else if (md.firstPage.equals("pining")) {
mPiningView.setVisibility(View.VISIBLE);
mKnownButton.setOnClickListener(this);
}
else {
// Set unset info
if (mThumb.getUrl() == null) {
mHeaderView.setVisibility(View.VISIBLE);
mColorfulBar.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid));
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryDetail.title);
mUploader.setText(mGalleryDetail.uploader);
mCategory.setText(Ui.getCategoryText(mGalleryDetail.category));
mCategory.setBackgroundColor(Ui.getCategoryColor(mGalleryDetail.category));
}
// Enable button
mReadButton.setEnabled(true);
mReadButton.setOnClickListener(this);
mRateButton.setEnabled(true);
mRateButton.setOnClickListener(this);
RatingBar rate = (RatingBar)mRootView.findViewById(R.id.detail_rate);
rate.setRating(mGalleryDetail.rating);
TextSwitcher averagePeople = (TextSwitcher)mRootView.findViewById(R.id.detail_average_people);
if (!isSetViewFactory) {
averagePeople.setFactory(this);
isSetViewFactory = true;
}
averagePeople.setCurrentText(String.format("%.2f (%d)",
mGalleryDetail.rating, mGalleryDetail.people));
TextView posted = (TextView)mRootView.findViewById(R.id.detail_posted);
posted.setText(mGalleryDetail.posted);
TextView language = (TextView)mRootView.findViewById(R.id.detail_language);
language.setText(String.format(getString(R.string.detail_language), mGalleryDetail.language));
TextView pagesSize = (TextView)mRootView.findViewById(R.id.detail_pages_size);
pagesSize.setText(String.format(getString(R.string.detail_pages_size),
mGalleryDetail.pages, mGalleryDetail.size));
addTags();
mNormalView.setVisibility(View.VISIBLE);
// paper list
if (mGalleryDetail.previewLists[0] != null) {
mPreviewListMain.setVisibility(View.VISIBLE);
// preview num
mBottomPanel.setVisibility(View.VISIBLE);
mPreviewNumText.setText(String.format("%d / %d",
1, mGalleryDetail.previewSum));
mPreviewRefreshButton.setOnClickListener(this);
// Init go to dialog or disable it
if (mGalleryDetail.previewSum > 1) {
mGoToDialog = createGoToDialog();
mPreviewNumText.setOnClickListener(this);
mBackButton.setOnClickListener(this);
mFrontButton.setOnClickListener(this);
} else {
mPreviewNumText.setClickable(false);
mBackButton.setClickable(false);
mFrontButton.setClickable(false);
}
mCurPage = 0;
mPreviewListLayout.removeAllViews();
mGalleryDetail.previewLists[0].setData(this, mActivity, mGalleryDetail, 0);
mGalleryDetail.previewLists[0].addPreview(mPreviewListLayout);
} else {
new SuperToast(mActivity, R.string.detail_preview_error, SuperToast.WARNING);
}
// Set comments
mActivity.setComments(mGalleryDetail.comments);
}
}
@Override
public void onClick(View v) {
if (v == mUploader) {
mActivity.finish();
Intent intent = new Intent(mActivity, GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE, ListUrls.MODE_UPLOADER);
intent.putExtra(GalleryListActivity.KEY_UPLOADER, mUploader.getText());
startActivity(intent);
} else if (v == mRateButton) {
rate(mGalleryDetail.rating);
} else if (v == mReadButton) {
mData.addRead(mGalleryDetail);
Intent intent = new Intent(mActivity,
GalleryActivity.class);
intent.putExtra("url", mGalleryDetail.firstPage);
intent.putExtra("gid", mGalleryDetail.gid);
intent.putExtra("title", mGalleryDetail.title);
intent.putExtra("firstPage", 0);
intent.putExtra("pageSum", mGalleryDetail.pages);
startActivity(intent);
} else if (v == mRefreshButton) {
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl, mGalleryDetail, listener);
// Delete refresh button
mRefreshButton.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mCancelButton
| v == mKnownButton) {
mActivity.finish();
} else if (v == mOnceButton) {
// TODO create a class uri
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl + "&nw=session", mGalleryDetail, listener);
// Delete offensiveView
mOffensiveView.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mEveryButton) {
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl + "&nw=always", mGalleryDetail, listener);
// Delete offensiveView
mOffensiveView.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mBackButton) {
if (mCurPage <= 0)
return;
mCurPage--;
refreshPageList();
} else if (v == mFrontButton) {
if (mCurPage >= mGalleryDetail.previewSum - 1)
return;
mCurPage++;
refreshPageList();
} else if (v == mPreviewRefreshButton) {
refreshPageList();
} else if (v == mPreviewNumText) {
mGoToDialog.show();
}
}
private int getSendableRating(float ratingFloat) {
float dr = ratingFloat*2;
return (int)(dr + 0.5);
}
@SuppressLint("InflateParams")
public void rate(float defaultRating) {
View view = mActivity.getLayoutInflater().inflate(R.layout.rate, null);
final TextView tv = (TextView)view.findViewById(R.id.rate_text);
final ProgressiveRatingBar rb = (ProgressiveRatingBar)view.findViewById(R.id.rate);
rb.setOnDrawListener(new ProgressiveRatingBar.OnDrawListener() {
@Override
public void onDraw(float rating) {
int textId = getResources().getIdentifier(mAppContext.getPackageName()
+ ":string/rating" + getSendableRating(rating), null, null);
if (textId == 0)
textId = R.string.rating0;
tv.setText(textId);
}
});
rb.setRating(defaultRating);
new DialogBuilder(mActivity).setTitle(R.string.rate)
.setView(view, true)
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(View v) {
int rating = getSendableRating(rb.getRating());
if (rating <= 0 || rating > 10)
new SuperToast(mActivity)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.invalid_rating)
.show();
else {
((AlertButton)v).dialog.dismiss();
mClient.rate(mGalleryDetail.gid, mGalleryDetail.token,
rating, new EhClient.OnRateListener() {
@Override
public void onSuccess(float ratingAvg,
int ratingCnt) {
mGalleryDetail.rating = ratingAvg;
mGalleryDetail.people = ratingCnt;
if (!mActivity.isFinishing()) {
//Reset start
RatingBar rate = (RatingBar)mRootView.findViewById(R.id.detail_rate);
rate.setRating(mGalleryDetail.rating);
TextSwitcher averagePeople = (TextSwitcher)
mRootView.findViewById(R.id.detail_average_people);
averagePeople.setText(String.format("%.2f (%d)",
mGalleryDetail.rating, mGalleryDetail.people));
}
new SuperToast(mActivity).setMessage(R.string.rate_succeeded).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(getString(R.string.rate_failed) + "\n" + eMsg)
.show();
}
});
}
}
}).setNegativeButton(android.R.string.cancel, new OnClickListener(){
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
}
}).create().show();
}
public List<Comment> getComments() {
if (mGalleryDetail == null)
return null;
else
return mGalleryDetail.comments;
}
private class GDetailGetListener
implements EhClient.OnGetGDetailListener {
@Override
public void onSuccess(GalleryDetail md) {
layout(md);
}
@Override
public void onFailure(String eMsg) {
// Delete progress bar
// Show refresh button
mWaitPb.setVisibility(View.GONE);
mRefreshButton.setVisibility(View.VISIBLE);
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(eMsg).show();
}
}
private class SimpleVote implements View.OnClickListener {
private final String groupName;
private final String tagText;
private final boolean isUp;
public SimpleVote(String groupName, String tagText, boolean isUp) {
this.groupName = groupName;
this.tagText = tagText;
this.isUp = isUp;
}
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
mClient.vote(mGalleryDetail.gid, mGalleryDetail.token,
groupName, tagText, isUp, new SimpleVoteListener());
}
}
private class SimpleVoteListener implements EhClient.OnVoteListener {
@Override
public void onSuccess(String tagPane) {
new SuperToast(mActivity).setMessage(R.string.vote_succeeded).show();
DetailParser parser = new DetailParser();
if (parser.parser(tagPane, DetailParser.TAG) ==
DetailParser.TAG) {
mGalleryDetail.tags = parser.tags;
addTags();
} else {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(R.string.em_parser_error).show();
}
}
@Override
public void onFailure(String eMsg) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(getString(R.string.vote_failed) + "\n"+ eMsg).show();
}
}
}
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.service.DownloadServiceConnection;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.DownloadItemLayout;
@@ -86,9 +86,9 @@ public class DownloadActivity extends AbstractActivity {
mServiceConn.getService().cancel(Download.getKey(longClickItemIndex));
mDlAdapter.notifyDataSetChanged();
// TODO 有人反馈 Download.get(longClickItemIndex).title 为空,看来很有必要在正则抓取时检查是否为空
File dir = new File(Config.getDownloadPath(), Util.rightFileName(Download.get(longClickItemIndex).title));
File dir = new File(Config.getDownloadPath(), Utils.rightFileName(Download.get(longClickItemIndex).title));
try {
Util.deleteContents(dir);
Utils.deleteContents(dir);
} catch (IOException e) {
e.printStackTrace();
}
@@ -67,7 +67,6 @@ import com.hippo.ehviewer.widget.ActionableToastBar.ActionClickedListener;
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.ProgressDialogBulider;
import com.hippo.ehviewer.widget.PullViewGroup;
import com.hippo.ehviewer.widget.RatingView;
@@ -148,9 +147,9 @@ public class FavouriteActivity extends AbstractGalleryActivity
super.onCreate(savedInstanceState);
mAppContext = (AppContext)getApplication();
mData = mAppContext.getData();
mData = Data.getInstance();
mResources =getResources();
mClient = mAppContext.getEhClient();
mClient = EhClient.getInstance();
final ActionBar actionBar = getActionBar();
getActionBar().setDisplayHomeAsUpEnabled(true);
@@ -267,7 +266,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
});
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
alignment.addOnFitSystemWindowsListener(new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -296,7 +295,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
// Check login
if (!mClient.isLogin()) {
SuperToast superToast = new SuperToast(this, "未检测到登陆状态,仅可使用本地收藏。由于开发者的问题,本地收藏不可靠,请尽快登陆,将本地收藏转移至账户中的收藏。");
SuperToast superToast = new SuperToast("未检测到登陆状态,仅可使用本地收藏。由于开发者的问题,本地收藏不可靠,请尽快登陆,将本地收藏转移至账户中的收藏。"); // TODO
superToast.setDuration(SuperToast.LENGTH_LONG);
superToast.show();
}
@@ -428,7 +427,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
mPdb = null;
mProgressDialog.dismiss();
mProgressDialog = null;
new SuperToast(this, R.string.move_successfully).show();
new SuperToast(R.string.move_successfully).show();
}
}
@@ -439,8 +438,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (mMenuIndex == position) {
new SuperToast(FavouriteActivity.this, R.string.dst_src_same,
SuperToast.WARNING).show();
new SuperToast(R.string.dst_src_same, SuperToast.WARNING).show();
return;
}
@@ -573,7 +571,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
mLastModifyGiList = gis;
mLastModifyPageNum = pageNum;
refresh();
new SuperToast(FavouriteActivity.this, mSuccStr).show();
new SuperToast(mSuccStr).show();
// add to local
if (mToLocal)
+58 -68
View File
@@ -24,6 +24,17 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
@@ -32,56 +43,43 @@ import com.hippo.ehviewer.gallery.data.ImageSet;
import com.hippo.ehviewer.gallery.ui.GLRootView;
import com.hippo.ehviewer.network.Downloader;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.SuperToast;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
public class GalleryActivity extends AbstractActivity {
private String TAG = "MangaActivity";
private final String TAG = "MangaActivity";
private AppContext mAppContext;
private EhClient mEhClient;
private RelativeLayout mainView;
private int gid;
private String title;
private int retryTimes = 0;
private static final int maxRetry = 3;
private boolean stopFlag = false;
// [firstPage, lastPage)
// last 是目前已下载的最后一页的 index + 1
private int pageSum;
private int firstPage;
private int lastPage;
private String allPrePageUrl;
private String allNextPageUrl;
private boolean getPrePage = false;
private boolean mStop = false;
private File mFolder;
private ImageSet mImageSet;
// two element, first is web url, second is image url
private List<String[]> imagesUrl;
// TODO use downloader to download image
// TODO combine it with MangaDownloadActivity
private class MangaUrlGetListener implements EhClient.OnGetMangaUrlListener {
@@ -93,12 +91,12 @@ public class GalleryActivity extends AbstractActivity {
return;
}
retryTimes = 0;
final int index = (Integer)checkFlag;
final String prePageUrl = arg[0];
final String nextPageUrl = arg[1];
final String imageUrl = arg[2];
String[] urls = imagesUrl.get(index);
if (urls == null) {
imagesUrl.set(index, urls = new String[2]);
@@ -117,9 +115,9 @@ public class GalleryActivity extends AbstractActivity {
if (index != firstPage - 1 && (index == firstPage && allPrePageUrl == null) && index != lastPage) {
Log.e(TAG, "targetPage != firstPage - 1 && (targetPage == firstPage && allPrePageUrl == null) && targetPage != lastPage");
}
final String imageName = String.format("%05d", index + 1) + "." + Util.getExtension(imageUrl);
final String imageName = String.format("%05d", index + 1) + "." + Utils.getExtension(imageUrl);
final Downloader downloader = new Downloader(GalleryActivity.this);
try {
downloader.resetData(mFolder.getPath(),
@@ -129,7 +127,7 @@ public class GalleryActivity extends AbstractActivity {
onFailure(checkFlag, mAppContext.getString(R.string.em_url_format_error));
e.printStackTrace();
}
// TODO threadpool
new Thread() {
@Override
@@ -138,14 +136,14 @@ public class GalleryActivity extends AbstractActivity {
if (testImage(mFolder.getPath(), imageName)) {
onGetImage(index, Downloader.COMPLETED, nextPageUrl);
} else {
downloader.run();
onGetImage(index, downloader.getStatus(), nextPageUrl);
}
}
}.start();
}
// TODO only test bitmap here
private boolean testImage(String path, String name) {
boolean isImage = false;
@@ -168,11 +166,11 @@ public class GalleryActivity extends AbstractActivity {
e.printStackTrace();
} finally {
if (fis != null)
Util.closeStreamQuietly(fis);
Utils.closeStreamQuietly(fis);
}
return isImage;
}
private void onGetImage(int index, int state, String nextPageUrl) {
if (state == Downloader.COMPLETED) {
mImageSet.changeState(index, ImageSet.STATE_LOADED);
@@ -189,7 +187,7 @@ public class GalleryActivity extends AbstractActivity {
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
if (stopFlag) {
@@ -199,11 +197,9 @@ public class GalleryActivity extends AbstractActivity {
retryTimes++;
int targetPage = (Integer)checkFlag;
if (retryTimes < maxRetry) {
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(eMsg + " " +
String.format(getString(R.string.em_retry_times), retryTimes))
.show(); // TODO
new SuperToast(eMsg + " " +
String.format(getString(R.string.em_retry_times), retryTimes),
SuperToast.WARNING).show(); // TODO
if (targetPage == firstPage - 1 &&
getPrePage == true) {
mEhClient.getMangaUrl(allPrePageUrl, targetPage, new MangaUrlGetListener());
@@ -217,21 +213,17 @@ public class GalleryActivity extends AbstractActivity {
if (targetPage == firstPage - 1 &&
getPrePage == true) {
getPrePage = false;
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.retry_max_pre).show();
new SuperToast(R.string.retry_max_pre, SuperToast.WARNING).show();
}
else {
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.retry_max_next).show();
new SuperToast(R.string.retry_max_next, SuperToast.WARNING).show();
mStop = true;
}
mImageSet.changeState(targetPage, ImageSet.STATE_FAIL);
}
}
}
@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
@@ -245,21 +237,21 @@ public class GalleryActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gl_root_group);
mAppContext = (AppContext)getApplication();
mEhClient = mAppContext.getEhClient();
mEhClient = EhClient.getInstance();
getActionBar().hide();
// For API < 16 Fullscreen
if (Build.VERSION.SDK_INT < 19) {
@@ -277,33 +269,31 @@ public class GalleryActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Intent intent = getIntent();
firstPage = intent.getIntExtra("firstPage", 0);
lastPage = firstPage;
gid = intent.getIntExtra("gid", 0);
title = intent.getStringExtra("title");
mFolder = new File(Config.getDownloadPath(), Util.rightFileName(title));
mFolder = new File(Config.getDownloadPath(), Utils.rightFileName(title));
if (mFolder.isFile())
mFolder.delete();
mFolder.mkdirs();
pageSum = intent.getIntExtra("pageSum", 0);
mImageSet = new ImageSet(this, gid, mFolder, pageSum, firstPage, lastPage, null);
GalleryView isv = new GalleryView(getApplicationContext(), mImageSet, firstPage);
isv.setOnEdgeListener(new GalleryView.OnEdgeListener() {
@Override
public void onLastPageEdge() {
new SuperToast(GalleryActivity.this)
.setMessage(R.string.last_page).show();
new SuperToast(R.string.last_page).show();
}
@Override
public void onFirstPageEdge() {
new SuperToast(GalleryActivity.this)
.setMessage(R.string.first_page).show();
new SuperToast(R.string.first_page).show();
}
});
isv.setOnTapTextListener(new GalleryView.OnTapTextListener() {
@Override
public void onTapText(int index) {
@@ -318,7 +308,7 @@ public class GalleryActivity extends AbstractActivity {
@Override
public void onTapDoubleText(int index) {
// TODO Auto-generated method stub
}
});
isv.setOnScrollPageListener(new GalleryView.OnScrollPageListener() {
@@ -329,7 +319,7 @@ public class GalleryActivity extends AbstractActivity {
mEhClient.getMangaUrl(allNextPageUrl, lastPage, new MangaUrlGetListener());
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
if (!getPrePage && allPrePageUrl != null
&& !allPrePageUrl.equals("first")
&& index == firstPage - 1) {
@@ -341,24 +331,24 @@ public class GalleryActivity extends AbstractActivity {
});
GLRootView glrv= (GLRootView)findViewById(R.id.gl_root_view);
glrv.setContentPane(isv);
String url = intent.getStringExtra("url");
allNextPageUrl = url;
allPrePageUrl = null;
if (firstPage == 0)
allPrePageUrl = "first";
if (firstPage == pageSum - 1)
allNextPageUrl = "last";
imagesUrl = new ArrayList<String[]>(Collections.nCopies(pageSum, (String[])null));
imagesUrl.set(lastPage, new String[]{url, null});
// Get image and next page
mEhClient.getMangaUrl(url, lastPage, new MangaUrlGetListener());
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
@Override
protected void onDestroy () {
stopFlag = true;
@@ -16,353 +16,573 @@
package com.hippo.ehviewer.ui;
import java.util.List;
import java.util.Stack;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.widget.ScrollView;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import com.hippo.ehviewer.Analytics;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.ImageLoader;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.ApiGalleryDetail;
import com.hippo.ehviewer.data.GalleryDetail;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.data.LofiGalleryDetail;
import com.hippo.ehviewer.data.LofiGalleryInfo;
import com.hippo.ehviewer.drawable.OvalDrawable;
import com.hippo.ehviewer.ehclient.DetailUrlParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.service.DownloadService;
import com.hippo.ehviewer.service.DownloadServiceConnection;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LoadImageView;
import com.hippo.ehviewer.widget.ProgressiveRatingBar;
import com.hippo.ehviewer.widget.RefreshTextView;
import com.hippo.ehviewer.widget.SuperButton;
import com.hippo.ehviewer.widget.SuperToast;
import com.hippo.ehviewer.windowsanimate.WindowsAnimate;
public class GalleryDetailActivity extends AbstractFragmentActivity
implements ActionBar.TabListener {
public class GalleryDetailActivity extends AbstractActivity
implements View.OnClickListener, FswView.OnFitSystemWindowsListener,
View.OnTouchListener , ViewSwitcher.ViewFactory,
ProgressiveRatingBar.OnUserRateListener {
@SuppressWarnings("unused")
private static final String TAG = "MangaDetailActivity";
private static final String TAG = GalleryDetailActivity.class.getSimpleName();
public static final String KEY_G_INFO = "gallery_info";
private ViewPager mViewPager;
private Stack<GalleryDetail> mGdList;
private GalleryDetail mGalleryDetail;
private Resources mResources;
private EhClient mClient;
private WindowsAnimate mWindowsAnimate;
private GalleryInfo mGalleryInfo;
private DetailSectionFragment mDetailFragment;
private CommentsSectionFragment mCommentsFragment;
private int mRunningAnimateNum = 0;
private boolean isCheckmark = false;
private boolean isSetDrawable = false;
private int mTabIndex;
private RefreshTextView mRefreshText;
private LoadImageView mThumb;
private TextView mTitle;
private TextView mUploader;
private SuperButton mDownloadButton;
private SuperButton mReadButton;
private TextView mCategory;
private TextView mMoreOfUploader;
private TextView mSimilar;
private final DownloadServiceConnection mServiceConn = new DownloadServiceConnection();
private TextSwitcher mRatingText;
private ProgressiveRatingBar mRating;
private TextView mFavorite;
private TextView mRate;
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
private ScrollView mDetailScroll;
private ScrollView mMoreDetailScroll;
private View mDetailHeader;
private View mDetailButtons;
private TextView mWarning;
private View mDetailActions;
private View mDividerAM;
private View mDetailMore;
private View mDividerMR;
private View mDetailRate;
private OvalDrawable mCategoryDrawable;
private Drawable mRateDrawable;
private Drawable mCheckmarkDrawable;
private GalleryInfo handleIntent(Intent intent) {
GalleryInfo gi = null;
if (intent.getAction() == "android.intent.action.VIEW") {
// Start from url
DetailUrlParser parser = new DetailUrlParser();
if (parser.parser(intent.getData().getPath())) {
if (Config.getMode() == EhClient.MODE_LOFI) {
// We can't get info from lofi detail, we need get info from api
gi = new ApiGalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
} else {
gi = new GalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
}
} else {
// If can not parser url, just keep it null
}
} else {
gi = (GalleryInfo)(intent.getParcelableExtra(KEY_G_INFO));
if (gi != null) {
if (gi instanceof LofiGalleryInfo)
gi = new LofiGalleryDetail((LofiGalleryInfo)gi);
else
gi = new GalleryDetail(gi);
}
}
return gi;
}
/*
@Override
protected void onNewIntent(Intent intent) {
if (mGalleryInfo != null)
mGiStack.push(mGalleryInfo);
setIntent(intent);
mGalleryInfo = handleIntent(intent);
if (mGalleryInfo == null) {
// TODO need a toast ?
if (mGiStack.isEmpty())
finish();
else
mGalleryInfo = mGiStack.pop();
} else {
doPreLayout();
}
}*/
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConn);
}
private GalleryDetail handleIntent(Intent intent) {
GalleryDetail gi = null;
if (intent.getAction() == "android.intent.action.VIEW") {
DetailUrlParser parser = new DetailUrlParser();
if (parser.parser(intent.getData().getPath())) {
gi = new GalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
} else {
// TODO
}
} else {
gi = new GalleryDetail((GalleryInfo)
(intent.getParcelableExtra(KEY_G_INFO)));
}
// Analytics
if (gi != null)
Analytics.openGallery(this, gi.gid, gi.token);
return gi;
mWindowsAnimate.free();
}
@Override
protected void onNewIntent(Intent intent) {
mGdList.push(mGalleryDetail);
setIntent(intent);
mGalleryDetail = handleIntent(intent);
loadDetail();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGalleryInfo = handleIntent(getIntent());
if (mGalleryInfo == null)
// If no GalleryInfo pass, just finish
finish();
setContentView(R.layout.gallery_detail);
setTitle(String.valueOf(mGalleryInfo.gid));
mClient = EhClient.getInstance();
mWindowsAnimate = new WindowsAnimate();
mWindowsAnimate.init(this);
mResources = getResources();
final ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// Get view
mDetailScroll = (ScrollView)findViewById(R.id.detail_scroll);
mMoreDetailScroll = (ScrollView)findViewById(R.id.more_detail_scroll);
mRefreshText = (RefreshTextView)findViewById(R.id.refresh_text);
mDetailHeader = findViewById(R.id.detail_header);
mDetailButtons = findViewById(R.id.detail_buttons);
mWarning = (TextView)findViewById(R.id.warning);
mDetailActions = findViewById(R.id.detail_actions);
mDividerAM = findViewById(R.id.detail_divider_a_m);
mDetailMore = findViewById(R.id.detail_more);
mDividerMR = findViewById(R.id.detail_divider_m_r);
mDetailRate = findViewById(R.id.detail_rate);
mThumb = (LoadImageView)findViewById(R.id.thumb);
mTitle = (TextView)findViewById(R.id.title);
mUploader = (TextView)findViewById(R.id.uploader);
mDownloadButton = (SuperButton)findViewById(R.id.download);
mReadButton = (SuperButton)findViewById(R.id.read);
mCategory = (TextView)findViewById(R.id.category);
mMoreOfUploader = (TextView)findViewById(R.id.more_of_uploader);
mSimilar = (TextView)findViewById(R.id.similar);
mRatingText = (TextSwitcher)mDetailRate.findViewById(R.id.rating_text);
mRating = (ProgressiveRatingBar)mDetailRate.findViewById(R.id.rating);
mFavorite = (TextView)findViewById(R.id.favorite);
mRate = (TextView)findViewById(R.id.rate);
// Get temp view
FswView alignment = (FswView)findViewById(R.id.alignment);
// Set Drawable
Rect rect = new Rect(0, 0, Ui.dp2pix(48), Ui.dp2pix(48));
mCategoryDrawable = new OvalDrawable(0);
mCategoryDrawable.setBounds(0, 0, Ui.dp2pix(48), Ui.dp2pix(48));
mCategory.setCompoundDrawables(null, mCategoryDrawable, null, null);
Drawable moreOfUploaderDrawable = mResources.getDrawable(R.drawable.ic_more_of_uploader);
moreOfUploaderDrawable.setBounds(rect);
mMoreOfUploader.setCompoundDrawables(null, moreOfUploaderDrawable, null, null);
Drawable similarDrawable = mResources.getDrawable(R.drawable.ic_similar);
similarDrawable.setBounds(rect);
mSimilar.setCompoundDrawables(null, similarDrawable, null, null);
Drawable favoriteDrawable = mResources.getDrawable(R.drawable.ic_favorite);
favoriteDrawable.setBounds(rect);
mFavorite.setCompoundDrawables(null, favoriteDrawable, null, null);
mRateDrawable = mResources.getDrawable(R.drawable.ic_rate);
mRateDrawable.setBounds(rect);
mCheckmarkDrawable = mResources.getDrawable(R.drawable.ic_checkmark);
mCheckmarkDrawable.setBounds(rect);
mRate.setCompoundDrawables(null, mRateDrawable, null, null);
// Set ripple
mWindowsAnimate.addRippleEffect(mCategory, false);
mWindowsAnimate.addRippleEffect(mMoreOfUploader, false);
mWindowsAnimate.addRippleEffect(mSimilar, false);
mWindowsAnimate.addRippleEffect(mFavorite, false);
// Init
mRatingText.setFactory(this);
// Set random color
int color = Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor();
int actionBarColor = color & 0x00ffffff | 0xdd000000;
Drawable drawable = new ColorDrawable(actionBarColor);
actionBar.setBackgroundDrawable(drawable);
Ui.translucent(this, actionBarColor);
mDownloadButton.setRoundBackground(true, mResources.getColor(R.color.background_light), color);
mDownloadButton.setTextColor(color);
mReadButton.setRoundBackground(true, color, 0);
((TextView)findViewById(R.id.detail_more_text)).setTextColor(color);
// Set listener
mDownloadButton.setOnClickListener(this);
mReadButton.setOnClickListener(this);
mCategory.setOnClickListener(this);
mMoreOfUploader.setOnClickListener(this);
mSimilar.setOnClickListener(this);
mRating.setOnUserRateListener(this);
mFavorite.setOnClickListener(this);
mRate.setOnClickListener(this);
mDetailMore.setOnTouchListener(this);
alignment.addOnFitSystemWindowsListener(this);
doPreLayout();
}
public void loadDetail() {
setTitle(String.valueOf(mGalleryDetail.gid));
mDetailFragment.handleDetail(mGalleryDetail);
getActionBar().setSelectedNavigationItem(0);
private void doPreLayout() {
String detailUrl = mClient.getDetailUrl(
mGalleryInfo.gid, mGalleryInfo.token);
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
if (galleryDetail.title == null) {
// TODO
// We should get info from detail page
} else {
mDetailScroll.setVisibility(View.VISIBLE);
mDetailHeader.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(galleryDetail.thumb, String.valueOf(galleryDetail.gid));
ImageLoader.getInstance(this).add(galleryDetail.thumb, String.valueOf(galleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(galleryDetail.title);
mUploader.setText(galleryDetail.uploader);
mClient.getGDetail(detailUrl, galleryDetail, new GDetailGetListener());
}
} else {
}
}
private String getRatingText(float rating) {
if (rating == Float.NaN)
return "(´_ゝ`)";
int resId = 0;
switch (Math.round(rating * 2)) {
case 0:
resId = R.string.rating0; break;
case 1:
resId = R.string.rating1; break;
case 2:
resId = R.string.rating2; break;
case 3:
resId = R.string.rating3; break;
case 4:
resId = R.string.rating4; break;
case 5:
resId = R.string.rating5; break;
case 6:
resId = R.string.rating6; break;
case 7:
resId = R.string.rating7; break;
case 8:
resId = R.string.rating8; break;
case 9:
resId = R.string.rating9; break;
case 10:
resId = R.string.rating10; break;
}
if (resId == 0)
return "(´_ゝ`)";
else
return getString(resId);
}
private String getAllRatingText(float rating, int people) {
return new StringBuilder().append("大家觉得").append(" ") // TODO
.append(getRatingText(rating))
.append(" (").append(rating).append(", ").append(people).append(")").toString();
}
/**
* GalleryDetail
* LofiGalleryDetail
* ApiGalleryDetail
*/
private void doLayout() {
if (mDetailHeader.getVisibility() == View.GONE) {
// If not set header in doPreLayout
mDetailHeader.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(mGalleryInfo.thumb, String.valueOf(mGalleryInfo.gid));
ImageLoader.getInstance(this).add(mGalleryInfo.thumb, String.valueOf(mGalleryInfo.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryInfo.title);
mUploader.setText(mGalleryInfo.uploader);
}
mDetailButtons.setVisibility(View.VISIBLE);
mWarning.setVisibility(View.VISIBLE);
mDetailActions.setVisibility(View.VISIBLE);
mDividerAM.setVisibility(View.VISIBLE);
mDetailMore.setVisibility(View.VISIBLE);
mDividerMR.setVisibility(View.VISIBLE);
mDetailRate.setVisibility(View.VISIBLE);
mCategory.setText(Ui.getCategoryText(mGalleryInfo.category));
mCategoryDrawable.setColor(Ui.getCategoryColor(mGalleryInfo.category));
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
// TODO set language
((TextView)mDetailMore.findViewById(R.id.language)).setText("语言: " + galleryDetail.language); // TODO
((TextView)mDetailMore.findViewById(R.id.posted)).setText(galleryDetail.posted);
((TextView)mDetailMore.findViewById(R.id.pages)).setText("页面: " + String.valueOf(galleryDetail.pages));
((TextView)mDetailMore.findViewById(R.id.size)).setText("大小: " + galleryDetail.size);
StringBuilder sb = new StringBuilder();
sb.append("gid: ").append(galleryDetail.gid).append("\n\n")
.append("token: ").append(galleryDetail.token).append("\n\n")
.append("title: ").append(galleryDetail.title).append("\n\n")
.append("title_jpn: ").append(galleryDetail.title_jpn).append("\n\n")
.append("thumb: ").append(galleryDetail.thumb).append("\n\n")
.append("category: ").append(Ui.getCategoryText(galleryDetail.category)).append("\n\n")
.append("uploader: ").append(galleryDetail.uploader).append("\n\n")
.append("posted: ").append(galleryDetail.posted).append("\n\n")
.append("pages: ").append(galleryDetail.pages).append("\n\n")
.append("size: ").append(galleryDetail.size).append("\n\n")
.append("resized: ").append(galleryDetail.resized).append("\n\n")
.append("parent: ").append(galleryDetail.parent).append("\n\n")
.append("visible: ").append(galleryDetail.visible).append("\n\n")
.append("language: ").append(galleryDetail.language).append("\n\n")
.append("people: ").append(galleryDetail.people).append("\n\n")
.append("rating: ").append(galleryDetail.rating);
((TextView)mMoreDetailScroll.findViewById(R.id.more_detail)).setText(sb.toString());
mRatingText.setCurrentText(getAllRatingText(galleryDetail.rating, galleryDetail.people));
mRating.setRating(galleryDetail.rating);
mRating.setEnableRate(false);
} else if (mGalleryInfo instanceof GalleryDetail) {
} else if (mGalleryInfo instanceof ApiGalleryDetail) {
}
}
@Override
public void onBackPressed() {
if (!mGdList.isEmpty()) {
mGalleryDetail = mGdList.pop();
loadDetail();
} else {
finish();
if (mRunningAnimateNum != 0 || mWindowsAnimate.isRunningAnimate())
return;
if (mDetailScroll.getVisibility() == View.VISIBLE) {
super.onBackPressed();
} else if (mMoreDetailScroll.getVisibility() == View.VISIBLE) {
mDetailScroll.setVisibility(View.VISIBLE);
ValueAnimator animation = ValueAnimator.ofInt(mMoreDetailScroll.getLeft(), mMoreDetailScroll.getRight());
animation.setDuration(Constants.ANIMATE_TIME);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int left = (Integer)animation.getAnimatedValue();
mMoreDetailScroll.setLeft(left);
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
mMoreDetailScroll.setVisibility(View.GONE);
mRunningAnimateNum--;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.setInterpolator(new AccelerateInterpolator());
animation.start();
mRunningAnimateNum++;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager);
public void onClick(View v) {
if (mRunningAnimateNum != 0 || mWindowsAnimate.isRunningAnimate())
return;
mGdList = new Stack<GalleryDetail>();
mGalleryDetail = handleIntent(getIntent());
final ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set random color
int color = Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor();
color = color & 0x00ffffff | 0xdd000000;
Drawable drawable = new ColorDrawable(color);
actionBar.setBackgroundDrawable(drawable);
Ui.translucent(this, color);
SectionsPagerAdapter adapter =
new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(adapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
if (v == mDownloadButton) {
} else if (v == mReadButton) {
//mData.addRead(mGalleryInfo);
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
Intent intent = new Intent(this,
GalleryActivity.class);
intent.putExtra("url", galleryDetail.firstPage);
intent.putExtra("gid", mGalleryInfo.gid);
intent.putExtra("title", mGalleryInfo.title);
intent.putExtra("firstPage", 0);
intent.putExtra("pageSum", galleryDetail.pages);
startActivity(intent);
} else {
// TODO
}
});
for (int i = 0; i < adapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(adapter.getPageTitle(i))
.setTabListener(this));
}
// Download service
Intent it = new Intent(GalleryDetailActivity.this, DownloadService.class);
bindService(it, mServiceConn, BIND_AUTO_CREATE);
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
mTabIndex = tab.getPosition();
invalidateOptionsMenu();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.detail, menu);
return true;
}
public List<Comment> getComments() {
if (mDetailFragment == null)
return null;
else
return mDetailFragment.getComments();
}
public void setComments(List<Comment> comments) {
if (mCommentsFragment != null)
mCommentsFragment.setComments(comments);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_favourite:
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(this, mGalleryDetail).show();
break;
case -1:
((AppContext)getApplication()).getData().addLocalFavourite(mGalleryDetail);
new SuperToast(this).setMessage(R.string.toast_add_favourite).show();
break;
default:
((AppContext)getApplication()).getEhClient().addToFavorite(mGalleryDetail.gid,
mGalleryDetail.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
} else if (v == mFavorite) {
Favorite.addToFavorite(this, mGalleryInfo);
} else if (v == mRate) {
if (isCheckmark) {
int rating = (int)(mRating.getRating() * 2 + 0.5);
if (rating <= 0 || rating > 10) {
new SuperToast(R.string.invalid_rating, SuperToast.ERROR).show();
return;
}
mClient.rate(mGalleryInfo.gid, mGalleryInfo.token, rating, new EhClient.OnRateListener() {
@Override
public void onSuccess() {
new SuperToast(GalleryDetailActivity.this).setMessage(R.string.toast_add_favourite).show();
public void onSuccess(float ratingAvg, int ratingCnt) {
mGalleryInfo.rating = ratingAvg;
// TODO mGalleryInfo.people = ratingCnt;
mRatingText.setText(getAllRatingText(mGalleryInfo.rating, ratingCnt));
mRating.setRating(mGalleryInfo.rating);
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryDetailActivity.this).setMessage(R.string.failed_to_add).show();
mRatingText.setText("评分失败"); // TODO
new SuperToast(eMsg, SuperToast.WARNING).show();
}
});
}
return true;
case R.id.action_download:
if (mGalleryDetail.language == null) {
new SuperToast(this).setMessage(R.string.wait).show();
mRatingText.setText("感谢评分"); // TODO
mRating.setEnableRate(false);
} else {
Intent it = new Intent(GalleryDetailActivity.this, DownloadService.class);
startService(it);
mServiceConn.getService().add(String.valueOf(mGalleryDetail.gid), mGalleryDetail.thumb,
EhClient.getDetailUrl(mGalleryDetail.gid, mGalleryDetail.token, 0, Config.getMode()),
mGalleryDetail.title);
new SuperToast(this, R.string.toast_add_download).show();
mRatingText.setText("请理智评分"); // TODO
mRating.setEnableRate(true);
}
return true;
case R.id.action_info:
if (mGalleryDetail.language == null) {
new SuperToast(this, R.string.wait).show();
} else {
new DialogBuilder(this).setTitle(R.string.info)
.setLongMessage(
"gid : " + mGalleryDetail.gid + "\n\n" +
"token : " + mGalleryDetail.token + "\n\n" +
"title : " + mGalleryDetail.title + "\n\n" +
"title_jpn : " + mGalleryDetail.title_jpn + "\n\n" +
"thumb : " + mGalleryDetail.thumb + "\n\n" +
"category : " + EhClient.getType(mGalleryDetail.category) + "\n\n" +
"uploader : " + mGalleryDetail.uploader + "\n\n" +
"posted : " + mGalleryDetail.posted + "\n\n" +
"pages : " + mGalleryDetail.pages + "\n\n" +
"size : " + mGalleryDetail.size + "\n\n" +
"resized : " + mGalleryDetail.resized + "\n\n" +
"parent : " + mGalleryDetail.parent + "\n\n" +
"visible : " + mGalleryDetail.visible + "\n\n" +
"language : " + mGalleryDetail.language + "\n\n" +
"people : " + mGalleryDetail.people + "\n\n" +
"rating : " + mGalleryDetail.rating)
.setMessageSelectable()
.setSimpleNegativeButton().create().show();
}
return true;
case R.id.action_reply:
final EditText et = new EditText(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
int x = Ui.dp2pix(8);
lp.leftMargin = x;
lp.rightMargin = x;
lp.topMargin = x;
lp.bottomMargin = x;
new DialogBuilder(this).setView(et, lp)
.setTitle(R.string.comment)
.setPositiveButton(R.string.send, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
String comment = et.getText().toString();
((AppContext)getApplication()).getEhClient()
.comment(EhClient.getDetailUrl(mGalleryDetail.gid, mGalleryDetail.token, 0, Config.getMode()),
comment, new EhClient.OnCommentListener() {
@Override
public void onSuccess(List<Comment> comments) {
setComments(comments);
mGalleryDetail.comments = comments;
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryDetailActivity.this, eMsg)
.setIcon(R.drawable.ic_warning).show();
}
});
// Animate to change
ValueAnimator animation = ValueAnimator.ofFloat(0.0f, 90.0f, 180.0f);
animation.setDuration(Constants.ANIMATE_TIME);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float rotationY = (Float)animation.getAnimatedValue();
if (rotationY > 90) {
rotationY = 180 - rotationY;
if (!isSetDrawable) {
mRate.setCompoundDrawables(null, isCheckmark ? mRateDrawable : mCheckmarkDrawable, null, null);
mRate.setText(isCheckmark ? R.string.rate : android.R.string.ok);
isSetDrawable = true;
isCheckmark = !isCheckmark;
}
}).setNegativeButton(android.R.string.cancel,
new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
}
}).create().show();
return true;
default:
return super.onOptionsItemSelected(item);
}
mRate.setRotationY(rotationY);
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
mRunningAnimateNum--;
isSetDrawable = false;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.start();
mRunningAnimateNum++;
}
}
@Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem info = menu.findItem(R.id.action_info);
MenuItem reply = menu.findItem(R.id.action_reply);
if (mTabIndex == 1) {
info.setVisible(false);
reply.setVisible(true);
} else {
info.setVisible(true);
reply.setVisible(false);
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
mMoreDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
if (v == mDetailMore) {
if (event.getAction() == MotionEvent.ACTION_UP &&
System.nanoTime() / 1000000 - event.getDownTime() < 100) {
mWindowsAnimate.addCircleTransitions(mDetailMore, (int)event.getX(),
(int)event.getY(), mResources.getColor(R.color.background_light),
new WindowsAnimate.OnAnimationEndListener() {
@Override
public void onAnimationEnd() {
mDetailScroll.setVisibility(View.GONE);
mMoreDetailScroll.setVisibility(View.VISIBLE);
mMoreDetailScroll.scrollTo(0, 0);
AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f);
aa.setDuration(Constants.ANIMATE_TIME);
mMoreDetailScroll.startAnimation(aa);
}
});
}
}
return true;
}
private class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
@Override
public void onUserRate(float rating) {
mRatingText.setText(getRatingText(rating));
}
@Override
public View makeView() {
TextView tv = new TextView(this);
tv.setGravity(Gravity.CENTER);
return tv;
}
private class GDetailGetListener
implements EhClient.OnGetGDetailListener {
@Override
public void onSuccess(GalleryDetail md) {
doLayout();
}
@Override
public Fragment getItem(int i) {
if (i == 0) {
return mDetailFragment = new DetailSectionFragment();
}
else if (i == 1) {
return mCommentsFragment = new CommentsSectionFragment();
}
else
return null;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
if (position == 0)
return getString(R.string.detail);
else
return getString(R.string.comment);
}
public void onFailure(String eMsg) {
// TODO
new SuperToast(eMsg, SuperToast.ERROR).show();
}
}
}
@@ -18,41 +18,39 @@ package com.hippo.ehviewer.ui;
import java.io.File;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.gallery.GalleryView;
import com.hippo.ehviewer.gallery.data.DownloadImageSet;
import com.hippo.ehviewer.gallery.ui.GLRootView;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.SuperToast;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
public class GalleryDownloadActivity extends AbstractActivity {
private static final String TAG = "MangaDownloadActivity";
public static final String KEY_TITLE = "title";
public static final String KEY_GID= "gid";
public static final String KEY_SIZE = "size";
public static final String KEY_END_INDEX = "endIndex";
private RelativeLayout mainView;
private DownloadImageSet mDownloadImageSet;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gl_root_group);
getActionBar().hide();
// For API < 16 Fullscreen
if (Build.VERSION.SDK_INT < 19) {
@@ -70,34 +68,34 @@ public class GalleryDownloadActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Intent intent = getIntent();
String title = intent.getStringExtra(KEY_TITLE);
int gid = intent.getIntExtra(KEY_GID, 0);
int size = intent.getIntExtra(KEY_SIZE, 1);
int endIndex = intent.getIntExtra(KEY_END_INDEX, 0);
GLRootView glrv= (GLRootView)findViewById(R.id.gl_root_view);
File folder = new File(Config.getDownloadPath(), Util.rightFileName(title));
File folder = new File(Config.getDownloadPath(), Utils.rightFileName(title));
folder.mkdirs();
mDownloadImageSet = new DownloadImageSet(this, gid, folder, size, 0, endIndex, null);
GalleryView isv = new GalleryView(getApplicationContext(), mDownloadImageSet, 0);
isv.setOnEdgeListener(new GalleryView.OnEdgeListener() {
@Override
public void onLastPageEdge() {
new SuperToast(GalleryDownloadActivity.this, R.string.last_page).show();
new SuperToast(R.string.last_page).show();
}
@Override
public void onFirstPageEdge() {
new SuperToast(GalleryDownloadActivity.this, R.string.first_page).show();
new SuperToast(R.string.first_page).show();
}
});
glrv.setContentPane(isv);
// Avoid error when use Movie
//glrv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
@@ -111,7 +109,7 @@ public class GalleryDownloadActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}
@Override
public void onDestroy() {
super.onDestroy();
@@ -83,13 +83,12 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
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;
@@ -217,7 +216,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
@Override
public void onFailure(String eMsg) {
setUserPanel();
new SuperToast(GalleryListActivity.this, eMsg).setIcon(R.drawable.ic_warning).show();
new SuperToast(eMsg, SuperToast.ERROR).show();
if (!GalleryListActivity.this.isFinishing())
loginDialog.show();
}
@@ -231,11 +230,11 @@ public class GalleryListActivity extends AbstractGalleryActivity
setUserPanel();
break;
case EhClient.NO_AVATAR:
new SuperToast(GalleryListActivity.this, "无头像").show(); // TODO
new SuperToast("无头像").show(); // TODO
break;
case EhClient.GET_AVATAR_ERROR:
default:
new SuperToast(GalleryListActivity.this, "获取头像失败", SuperToast.ERROR).show(); // TODO
new SuperToast("获取头像失败", SuperToast.ERROR).show(); // TODO
break;
}
}
@@ -500,10 +499,10 @@ public class GalleryListActivity extends AbstractGalleryActivity
String filePath = (String)mSearchImageText.getText();
File file = new File(filePath);
if (!file.exists()) {
new SuperToast(this, "图片不存在", SuperToast.ERROR).show();
new SuperToast("图片不存在", SuperToast.ERROR).show();
} else {
if (!file.canRead()) {
new SuperToast(this, "图片不可读", SuperToast.ERROR).show();
new SuperToast("图片不可读", SuperToast.ERROR).show();
} else {
CheckBox similar = (CheckBox)view.findViewById(R.id.checkboxSimilar);
@@ -532,28 +531,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
switch (position) {
case 0: // Add favourite item
gi = getGalleryInfo(longClickItemIndex);
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(GalleryListActivity.this, gi).show();
break;
case -1:
((AppContext)getApplication()).getData().addLocalFavourite(gi);
new SuperToast(GalleryListActivity.this).setMessage(R.string.toast_add_favourite).show();
break;
default:
((AppContext)getApplication()).getEhClient().addToFavorite(gi.gid,
gi.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(GalleryListActivity.this).setMessage(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryListActivity.this).setMessage(R.string.failed_to_add).show();
}
});
}
Favorite.addToFavorite(GalleryListActivity.this, gi);
break;
case 1:
gi = getGalleryInfo(longClickItemIndex);
@@ -561,7 +539,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
startService(it);
mServiceConn.getService().add(String.valueOf(gi.gid), gi.thumb,
mClient.getDetailUrl(gi.gid, gi.token), gi.title);
new SuperToast(GalleryListActivity.this, R.string.toast_add_download).show();
new SuperToast(R.string.toast_add_download).show();
break;
default:
break;
@@ -599,8 +577,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
if (targetPage < 0 || targetPage >= getPageNum())
throw new Exception();
} catch(Exception e) {
new SuperToast(GalleryListActivity.this, R.string.toast_invalid_page,
SuperToast.ERROR).show();
new SuperToast(R.string.toast_invalid_page, SuperToast.ERROR).show();
return;
}
@@ -641,9 +618,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onClick(View v) {
String key = et.getText().toString();
if (key.length() == 0)
new SuperToast(GalleryListActivity.this, R.string.tag_name_empty).setIcon(R.drawable.ic_warning).show();
new SuperToast(R.string.tag_name_empty, SuperToast.WARNING).show();
else if (listMenuTag.contains(key) && !key.equals(oldStr))
new SuperToast(GalleryListActivity.this, R.string.tag_name_empty).setIcon(R.drawable.ic_warning).show();
new SuperToast(R.string.tag_name_empty, SuperToast.WARNING).show();
else {
((AlertButton)v).dialog.dismiss();
if (listener != null) {
@@ -678,11 +655,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
if (searchNormal.getVisibility() == View.GONE) {
searchNormal.setVisibility(View.VISIBLE);
searchTag.setVisibility(View.GONE);
new SuperToast(GalleryListActivity.this, R.string.toast_normal_mode).show();
} else {
searchNormal.setVisibility(View.GONE);
searchTag.setVisibility(View.VISIBLE);
new SuperToast(GalleryListActivity.this, R.string.toast_tag_mode).show();
}
}
}).setPositiveButton(android.R.string.ok, new View.OnClickListener() {
@@ -913,8 +888,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mData = mAppContext.getData();
mClient = mAppContext.getEhClient();
mData = Data.getInstance();
mClient = EhClient.getInstance();
mResources =getResources();
handleIntent(getIntent());
@@ -1154,7 +1129,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
});
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
alignment.addOnFitSystemWindowsListener(new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -1345,7 +1320,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onBackPressed() {
if (System.currentTimeMillis() - curBackTime > BACK_PRESSED_INTERVAL) {
curBackTime = System.currentTimeMillis();
new SuperToast(GalleryListActivity.this, R.string.exit_tip).show();
new SuperToast(R.string.exit_tip).show();
} else
finish();
}
@@ -1418,7 +1393,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
@Override
public void onSuccess(String version, long size,
final String url, final String fileName, String info) {
String sizeStr = Util.sizeToString(size);
String sizeStr = Utils.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(GalleryListActivity.this,
version, sizeStr, info,
new View.OnClickListener() {
@@ -1540,9 +1515,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
listener.onSuccess(mAdapter, taskStamp, gis, gis.size() == 0 ? 0 : 1);
// Show update time
if (timeStamp != -1 && Config.getShowPopularUpdateTime())
new SuperToast(GalleryListActivity.this,
String.format(getString(R.string.popular_update_time),
mAppContext.getDateFormat().format(timeStamp))).show();
new SuperToast(String.format(getString(R.string.popular_update_time),
AppContext.sFormatter.format(timeStamp))).show();
}
@Override
public void onFailure(String eMsg) {
@@ -61,7 +61,7 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.CategoryTable;
import com.hippo.ehviewer.widget.DialogBuilder;
@@ -291,7 +291,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
Config.screenOriPre2Value(Integer.parseInt((String) newValue)));
} else if (KEY_RANDOM_THEME_COLOR.equals(key)) {
new SuperToast(mActivity, R.string.restart_to_take_effect).show();
new SuperToast(R.string.restart_to_take_effect).show();
mThemeColor.setEnabled(!(Boolean)newValue);
}
@@ -443,7 +443,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
private static void setExculdeTagGroup(TableLayout tl, int value) {
for (int i = 0; i < EXCULDE_TAG_GROUP_RESID.length; i++) {
CheckBox cb = (CheckBox)tl.findViewById(EXCULDE_TAG_GROUP_RESID[i]);
cb.setChecked(Util.int2boolean(value & EXCULDE_TAG_GROUP_ID[i]));
cb.setChecked(Utils.int2boolean(value & EXCULDE_TAG_GROUP_ID[i]));
}
}
@@ -647,8 +647,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
@Override
public void onClick(View v) {
if (!fileExplorerView.canWrite())
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(R.string.cur_dir_not_writable).show();
new SuperToast(R.string.cur_dir_not_writable, SuperToast.WARNING).show();
else {
String downloadPath = fileExplorerView.getCurPath();
@@ -756,14 +755,14 @@ public class SettingsActivity extends AbstractPreferenceActivity {
InputStream is = mActivity.getResources()
.openRawResource(R.raw.change_log);
new DialogBuilder(mActivity).setTitle(R.string.changelog)
.setLongMessage(Util.InputStream2String(is, "utf-8"))
.setLongMessage(Utils.InputStream2String(is, "utf-8"))
.setSimpleNegativeButton().create().show();
} else if (KEY_THANKS.equals(key)) {
InputStream is = mActivity.getResources()
.openRawResource(R.raw.thanks);
final WebView webView = new WebView(mActivity);
webView.loadData(Util.InputStream2String(is, "utf-8"), "text/html; charset=UTF-8", null);
webView.loadData(Utils.InputStream2String(is, "utf-8"), "text/html; charset=UTF-8", null);
new DialogBuilder(mActivity).setTitle(R.string.thanks)
.setView(webView, false).setSimpleNegativeButton()
.create().show();
@@ -787,7 +786,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
public void onSuccess(String version, long size,
final String url, final String fileName, String info) {
mCheckUpdate.setSummary(R.string.found_update);
String sizeStr = Util.sizeToString(size);
String sizeStr = Utils.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(
mActivity, version, sizeStr, info,
new View.OnClickListener() {
+1 -1
View File
@@ -226,7 +226,7 @@ public class Config {
}
public static void setUpdateDate() {
setUpdateDate(Util.getDate());
setUpdateDate(Utils.getDate());
}
public static void setUpdateDate(int date) {
+12 -1
View File
@@ -16,7 +16,18 @@
package com.hippo.ehviewer.util;
public class Constants {
public final class Constants {
public static final int FALSE = 0;
public static final int TRUE = 1;
public static final int ANIMATE_TIME = 300;
public static final int HTTP_TEMP_REDIRECT = 307;
public static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36";
public static String userAgent = System.getProperty("http.agent", defaultUserAgent);
public static final int DEFAULT_TIMEOUT = 10 * 1000;
public static final int MAX_REDIRECTS = 5;
public static final int BUFFER_SIZE = 4096;
}
+18 -19
View File
@@ -34,35 +34,34 @@ import android.os.Build;
import android.os.Environment;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.util.Log;
public class Crash {
private static final String TAG = "Crash";
private static Context mContext;
private static String externalCrashFilePath = "/EhViewer/crash";
private static String internalCrashFilePath = "/crash";
private static final String NEW_CRAHS = "new_crash";
private static final String LAST_CRASH_POSITION = "last_crash_position";
private static final String LAST_CRASH_NAME = "last_crash_name";
private static boolean mInit = false;
/**
* Init Crash
*
*
* @param context Application context
*/
public static void init(Context context) {
if (mInit)
return;
mInit = true;
mContext = context;
}
/**
* Is init
* @return True if init
@@ -70,16 +69,16 @@ public class Crash {
public static boolean isInit() {
return mInit;
}
/**
* Save throwable infomation to file
*
*
* @param ex The throwable to store
*/
public static void saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
collectDeviceInfo(sb);
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
@@ -95,7 +94,7 @@ public class Crash {
sb.append(result);
try {
long timestamp = System.currentTimeMillis();
String time = ((AppContext)mContext).getDateFormat().format(new Date());
String time = AppContext.sFormatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
String path = null;
boolean position = false;
@@ -125,7 +124,7 @@ public class Crash {
Log.e(TAG, "An error occured while writing crash file...", e);
}
}
private static void collectDeviceInfo(StringBuffer sb) {
try {
PackageManager pm = mContext.getPackageManager();
@@ -167,22 +166,22 @@ public class Crash {
sb.append("SDK=" + Build.VERSION.SDK_INT + "\n");
sb.append("\n");
}
/**
* Check is there last crash
*
*
* @return Return the crash String or null if there is no
*/
public static String getLastCrash() {
SharedPreferences configPre = mContext.getSharedPreferences("config", 0);
if (!configPre.getBoolean(NEW_CRAHS, false))
return null;
boolean position = configPre.getBoolean(LAST_CRASH_POSITION, false);
String lastCrashName;
if ((lastCrashName = configPre.getString(LAST_CRASH_NAME, null)) == null)
return null;
File lastCrashFile;
if (position) {
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
@@ -194,7 +193,7 @@ public class Crash {
}
if (!lastCrashFile.isFile())
return null;
try {
byte[] buffer = new byte[(int) lastCrashFile.length()];
DataInputStream din = new DataInputStream(new FileInputStream(lastCrashFile));
+8 -8
View File
@@ -65,7 +65,7 @@ public class Download {
}
private static void getDownloadInfo() {
String[] allOrder = Util.getStrings(mDownloadInfoPre, LIST_ORDER);
String[] allOrder = Utils.getStrings(mDownloadInfoPre, LIST_ORDER);
if (allOrder == null)
return;
@@ -87,7 +87,7 @@ public class Download {
mDownloadInfos.add(di);
}
if (errorFlag)
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
}
/**
@@ -102,7 +102,7 @@ public class Download {
if (mListOrder.indexOf(key) == -1) {
mListOrder.add(key);
mDownloadInfos.add(di);
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
mDownloadInfoPre.edit().putString(key, encode(di)).apply();
return true;
} else
@@ -127,7 +127,7 @@ public class Download {
String temp1 = mListOrder.get(indexOne);
mListOrder.set(indexOne, mListOrder.get(indexTwo));
mListOrder.set(indexTwo, temp1);
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
DownloadInfo temp2 = mDownloadInfos.get(indexOne);
mDownloadInfos.set(indexOne, mDownloadInfos.get(indexTwo));
@@ -151,7 +151,7 @@ public class Download {
mListOrder.remove(index);
mDownloadInfos.remove(index);
mDownloadInfoPre.edit().remove(key).apply();
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
return true;
} else
return false;
@@ -167,7 +167,7 @@ public class Download {
mDownloadInfos.remove(index);
String key = mListOrder.remove(index);
mDownloadInfoPre.edit().remove(key).apply();
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
return true;
}
@@ -221,11 +221,11 @@ public class Download {
e.printStackTrace();
}
}
return Util.byteArrayToHexString(os.toByteArray());
return Utils.byteArrayToHexString(os.toByteArray());
}
protected static DownloadInfo decode(String strDi) {
byte[] bytes = Util.hexStringToByteArray(strDi);
byte[] bytes = Utils.hexStringToByteArray(strDi);
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
DownloadInfo di = null;
try {
+45 -23
View File
@@ -16,19 +16,9 @@
package com.hippo.ehviewer.util;
import com.hippo.ehviewer.Analytics;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ui.GalleryDetailActivity;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.SuperToast;
import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -36,26 +26,58 @@ import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Data;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.SuperToast;
public class Favorite {
private static Context mContext;
private static Resources mResources;
private static AlertDialog lastAddToFavoriteDialog;
public static String[] FAVORITE_TITLES;
public static void init(Context context) {
mContext = context;
mResources = mContext.getResources();
FAVORITE_TITLES = new String[EhClient.FAVORITE_SLOT_NUM + 1];
FAVORITE_TITLES[0] = mResources.getString(R.string.local_favorite);
for (int i = 1; i < EhClient.FAVORITE_SLOT_NUM + 1; i++) {
FAVORITE_TITLES[i] = mResources.getString(R.string.favourite) + " "+ (i - 1);
}
}
public static void addToFavorite(final Context context, GalleryInfo gi) {
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(context, gi).show();
break;
case -1:
Data.getInstance().addLocalFavourite(gi);
new SuperToast(R.string.toast_add_favourite).show();
break;
default:
EhClient.getInstance().addToFavorite(gi.gid,
gi.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(R.string.failed_to_add).show();
}
});
}
}
public static AlertDialog getAddToFavoriteDialog(final Context context, final GalleryInfo gi) {
DialogBuilder db = new DialogBuilder(context).setView(R.layout.add_to_favorite, false);
db.setTitle(R.string.where_to_add);
@@ -71,25 +93,25 @@ public class Favorite {
int position, long id) {
lastAddToFavoriteDialog.dismiss();
lastAddToFavoriteDialog = null;
if (cb.isChecked())
Config.setDefaultFavorite(position - 1);
switch (position) {
case 0:
((AppContext)mContext).getData().addLocalFavourite(gi);
new SuperToast(context).setMessage(R.string.toast_add_favourite).show();
Data.getInstance().addLocalFavourite(gi);
new SuperToast(R.string.toast_add_favourite).show();
break;
default:
((AppContext)mContext).getEhClient().addToFavorite(gi.gid,
EhClient.getInstance().addToFavorite(gi.gid,
gi.token, position - 1, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(context).setMessage(R.string.toast_add_favourite).show();
new SuperToast(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(context).setMessage(R.string.failed_to_add).show();
new SuperToast(R.string.failed_to_add).show();
}
});
}
+179
View File
@@ -0,0 +1,179 @@
/*
* 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.util;
import java.util.Random;
public final class MathUtils {
private static final Random sRandom = new Random();
private static final float DEG_TO_RAD = 0.01745329F;
private static final float RAD_TO_DEG = 57.295784F;
public static float abs(float v) {
return v > 0.0F ? v : -v;
}
public static int constrain(int amount, int low, int high) {
return amount > high ? high : amount < low ? low : amount;
}
public static long constrain(long amount, long low, long high) {
return amount > high ? high : amount < low ? low : amount;
}
public static float constrain(float amount, float low, float high) {
return amount > high ? high : amount < low ? low : amount;
}
public static float log(float a) {
return (float) Math.log(a);
}
public static float exp(float a) {
return (float) Math.exp(a);
}
public static float pow(float a, float b) {
return (float) Math.pow(a, b);
}
public static float max(float a, float b) {
return a > b ? a : b;
}
public static float max(int a, int b) {
return a > b ? a : b;
}
public static float max(float a, float b, float c) {
return b > c ? b : a > b ? c : a > c ? a : c;
}
public static float max(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
}
public static float min(float a, float b) {
return a < b ? a : b;
}
public static float min(int a, int b) {
return a < b ? a : b;
}
public static float min(float a, float b, float c) {
return b < c ? b : a < b ? c : a < c ? a : c;
}
public static float min(int a, int b, int c) {
return a < b ? a < c ? a : c : b < c ? b : c;
}
public static float dist(float x1, float y1, float x2, float y2) {
float x = x2 - x1;
float y = y2 - y1;
return (float) Math.sqrt(x * x + y * y);
}
public static float dist(float x1, float y1, float z1, float x2, float y2,
float z2) {
float x = x2 - x1;
float y = y2 - y1;
float z = z2 - z1;
return (float) Math.sqrt(x * x + y * y + z * z);
}
public static float mag(float a, float b) {
return (float) Math.sqrt(a * a + b * b);
}
public static float mag(float a, float b, float c) {
return (float) Math.sqrt(a * a + b * b + c * c);
}
public static float sq(float v) {
return v * v;
}
public static float radians(float degrees) {
return degrees * 0.01745329F;
}
public static float degrees(float radians) {
return radians * 57.295784F;
}
public static float acos(float value) {
return (float) Math.acos(value);
}
public static float asin(float value) {
return (float) Math.asin(value);
}
public static float atan(float value) {
return (float) Math.atan(value);
}
public static float atan2(float a, float b) {
return (float) Math.atan2(a, b);
}
public static float tan(float angle) {
return (float) Math.tan(angle);
}
public static float lerp(float start, float stop, float amount) {
return start + (stop - start) * amount;
}
public static float norm(float start, float stop, float value) {
return (value - start) / (stop - start);
}
public static float map(float minStart, float minStop, float maxStart,
float maxStop, float value) {
return maxStart + (maxStart - maxStop)
* ((value - minStart) / (minStop - minStart));
}
public static int random(int howbig) {
return (int) (sRandom.nextFloat() * howbig);
}
public static int random(int howsmall, int howbig) {
if (howsmall >= howbig)
return howsmall;
return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
}
public static float random(float howbig) {
return sRandom.nextFloat() * howbig;
}
public static float random(float howsmall, float howbig) {
if (howsmall >= howbig)
return howsmall;
return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
}
public static void randomSeed(long seed) {
sRandom.setSeed(seed);
}
}
+14 -28
View File
@@ -31,33 +31,19 @@ public final class Theme {
public static final ColorDrawable GREY_DRAWABLE =
new ColorDrawable(0xffaaaaaa);
/**
* Colors from colors_material.xml
*
* material_red_300, material_red_500, material_red_700,
* material_red_A200, material_blue_500, material_blue_700,
* material_blue_A200, material_blue_A400, material_teal_700,
* material_green_500, material_green_700, material_lime_700,
* material_yellow_500, material_yellow_700, material_orange_500,
* material_orange_700, material_orange_A400, material_deep_orange_500,
* material_deep_orange_700, material_deep_orange_A200,
* material_deep_orange_A400, material_grey_600, material_grey_700,
* material_blue_grey_500, material_blue_grey_600,
* material_blue_grey_700, material_blue_grey_800,
* material_brown_500, material_brown_700
/*
* 赤 0xffc53929
* 橙 0xffff9100
* Lime 0xffafb42b;
* 绿 0xff0b8043
* 青 0xff0097a7
* 蓝 0xff3367d6
* 紫 0xff9c27b0
* 棕 0xff795548
*/
private static final int[] DARK_COLOR_TABLE = {
0xffe67c73, 0xffdb4437, 0xffc53929, 0xffff5252,
0xff4285f4, 0xff3367d6, 0xff448aff, 0xff2979ff,
0xff0097a7,
0xff0f9d58, 0xff0b8043,
0xffafb42b,
0xfff4b400, 0xfff09300,
0xffff9800, 0xfff57c00, 0xffff9100,
0xffff5722, 0xffc53929, 0xffff5252, 0xffff1744,
0xff757575, 0xff717171,
0xff607d8b, 0xff546e7a, 0xff455a64, 0xff37474f,
0xff795548, 0xff5d4037
0xffc53929, 0xffff9100, 0xffafb42b, 0xff0b8043,
0xff0097a7, 0xff3367d6, 0xff9c27b0, 0xff795548
};
/**
@@ -74,9 +60,9 @@ public final class Theme {
* @return
*/
public static int getDarkerColor(int color) {
return (((color & 0xff0000) >> 1) & 0xff0000)
| (((color & 0xff00) >> 1) & 0xff00)
| (((color & 0xff) >> 1) & 0xff)
return ((int)((color & 0xff0000) * 0.8) & 0xff0000)
| ((int)((color & 0xff00) * 0.8) & 0xff00)
| ((int)((color & 0xff) * 0.8) & 0xff)
| (color & 0xff000000);
}
+2 -4
View File
@@ -43,15 +43,14 @@ import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig
public class Ui {
@SuppressWarnings("unused")
private static final String TAG = "Ui";
private static final String TAG = Ui.class.getSimpleName();
private static Context mContext;
private static Resources mResources;
private static final BitmapFactory.Options opt = new BitmapFactory.Options();
private static float mDensity;
public static float mDensity;
public static int HOLO_BLUE_DARK;
public static int LIST_MAIN_BG;
public static int DOUJINSHI_BG_COLOR;
public static int MANGA_BG_COLOR;
@@ -91,7 +90,6 @@ public class Ui {
// init color
HOLO_BLUE_DARK = mResources.getColor(android.R.color.holo_blue_dark);
LIST_MAIN_BG = mResources.getColor(R.color.list_main_bg);
DOUJINSHI_BG_COLOR = mResources.getColor(R.color.doujinshi_bg);
MANGA_BG_COLOR = mResources.getColor(R.color.manga_bg);
@@ -33,8 +33,9 @@ import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.view.ViewParent;
public class Util {
public class Utils {
@SuppressWarnings("unused")
private static String TAG = "Util";
@@ -134,12 +135,12 @@ public class Util {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String str = null;
try {
Util.copy(is, baos, 1024);
Utils.copy(is, baos, 1024);
str = baos.toString(charset);
} catch (IOException e) {
e.printStackTrace();
} finally {
Util.closeStreamQuietly(baos);
Utils.closeStreamQuietly(baos);
}
return str;
}
@@ -157,7 +158,7 @@ public class Util {
String str = shaper.getString(key, null);
if (str == null || str.length() == 0)
return null;
return new String(Util.hexStringToByteArray(str)).split("\n");
return new String(Utils.hexStringToByteArray(str)).split("\n");
}
public static void putStrings(SharedPreferences shaper, String key, List<String> strs) {
@@ -314,4 +315,40 @@ public class Util {
public static final boolean int2boolean(int integer) {
return integer == 0 ? false : true;
}
public static void getCenterInWindows(View view, int[] location) {
getLocationInWindow(view, location);
location[0] += view.getWidth() / 2;
location[1] += view.getHeight() / 2;
}
public static void getLocationInWindow(View view, int[] location) {
if (location == null || location.length < 2) {
throw new IllegalArgumentException("location must be an array of two integers");
}
float[] position = new float[2];
position[0] = view.getLeft();
position[1] = view.getTop();
ViewParent viewParent = view.getParent();
while (viewParent instanceof View) {
view = (View)viewParent;
if (view.getId() == android.R.id.content) {
break;
}
position[0] -= view.getScrollX();
position[1] -= view.getScrollY();
position[0] += view.getLeft();
position[1] += view.getTop();
viewParent = view.getParent();
}
location[0] = (int) (position[0] + 0.5f);
location[1] = (int) (position[1] + 0.5f);
}
}
@@ -23,7 +23,7 @@ import android.widget.TableLayout;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class CategoryTable extends TableLayout {
@@ -73,16 +73,16 @@ public class CategoryTable extends TableLayout {
* @param category
*/
public void setCategory(int category) {
mDoujinshi.setChecked(!Util.int2boolean(category & ListUrls.DOUJINSHI));
mManga.setChecked(!Util.int2boolean(category & ListUrls.MANGA));
mArtistCG.setChecked(!Util.int2boolean(category & ListUrls.ARTIST_CG));
mGameCG.setChecked(!Util.int2boolean(category & ListUrls.GAME_CG));
mWestern.setChecked(!Util.int2boolean(category & ListUrls.WESTERN));
mNonH.setChecked(!Util.int2boolean(category & ListUrls.NON_H));
mImageSets.setChecked(!Util.int2boolean(category & ListUrls.IMAGE_SET));
mCosplay.setChecked(!Util.int2boolean(category & ListUrls.COSPLAY));
mAsianPorn.setChecked(!Util.int2boolean(category & ListUrls.ASIAN_PORN));
mMisc.setChecked(!Util.int2boolean(category & ListUrls.MISC));
mDoujinshi.setChecked(!Utils.int2boolean(category & ListUrls.DOUJINSHI));
mManga.setChecked(!Utils.int2boolean(category & ListUrls.MANGA));
mArtistCG.setChecked(!Utils.int2boolean(category & ListUrls.ARTIST_CG));
mGameCG.setChecked(!Utils.int2boolean(category & ListUrls.GAME_CG));
mWestern.setChecked(!Utils.int2boolean(category & ListUrls.WESTERN));
mNonH.setChecked(!Utils.int2boolean(category & ListUrls.NON_H));
mImageSets.setChecked(!Utils.int2boolean(category & ListUrls.IMAGE_SET));
mCosplay.setChecked(!Utils.int2boolean(category & ListUrls.COSPLAY));
mAsianPorn.setChecked(!Utils.int2boolean(category & ListUrls.ASIAN_PORN));
mMisc.setChecked(!Utils.int2boolean(category & ListUrls.MISC));
}
/**
@@ -60,4 +60,9 @@ public class FswView extends View {
paddingRight, paddingBottom);
return re;
}
public interface OnFitSystemWindowsListener {
void onfitSystemWindows(int paddingLeft,
int paddingTop, int paddingRight, int paddingBottom);
}
}
@@ -1,22 +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;
public interface OnFitSystemWindowsListener {
void onfitSystemWindows(int paddingLeft,
int paddingTop, int paddingRight, int paddingBottom);
}
@@ -20,37 +20,58 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RatingBar;
public class ProgressiveRatingBar extends RatingBar {
@SuppressLint("ClickableViewAccessibility")
public class ProgressiveRatingBar extends RatingBar
implements View.OnTouchListener {
private OnDrawListener mListener;
private boolean mEnableRate = true;
private OnUserRateListener mListener;
public ProgressiveRatingBar(Context context) {
super(context);
setOnTouchListener(this);
}
public ProgressiveRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
setOnTouchListener(this);
}
public ProgressiveRatingBar(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
setOnTouchListener(this);
}
public void setEnableRate(boolean enableRate) {
mEnableRate = enableRate;
}
@SuppressLint("WrongCall")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mEnableRate)
return false;
else
return true;
}
@Override
@SuppressLint("WrongCall")
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mListener != null)
mListener.onDraw(getRating());
if (isPressed() && mListener != null) {
mListener.onUserRate(getRating());
}
}
public void setOnDrawListener(OnDrawListener l) {
public void setOnUserRateListener(OnUserRateListener l) {
mListener = l;
}
public interface OnDrawListener {
void onDraw(float rating);
public interface OnUserRateListener {
void onUserRate(float rating);
}
}
+12 -11
View File
@@ -16,8 +16,6 @@
package com.hippo.ehviewer.widget;
import com.hippo.ehviewer.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -26,6 +24,8 @@ import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import com.hippo.ehviewer.R;
public class RatingView extends View {
private static boolean mInit = false;
private static Bitmap EMPTY_START;
@@ -33,9 +33,9 @@ public class RatingView extends View {
private static Bitmap FULL_START;
private static int mAWidth;
private static int mHeight;
private int mRating;
public RatingView(Context context) {
super(context);
init(context);
@@ -48,11 +48,11 @@ public class RatingView extends View {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
if (mInit)
return;
Resources resources = context.getResources();
FULL_START = BitmapFactory.decodeResource(resources, R.drawable.star_small);
HALF_START = BitmapFactory.decodeResource(resources, R.drawable.star_small_half);
@@ -61,21 +61,21 @@ public class RatingView extends View {
mHeight = FULL_START.getHeight();
mInit = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mAWidth * 5, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int step = 0;
int fullNum = mRating / 2;
int halfNum = mRating % 2;
int emptyNum = 5 - fullNum - halfNum;
for (int i = 0; i < fullNum; i++, step++)
canvas.drawBitmap(FULL_START, step * mAWidth, 0, null);
for (int i = 0; i < halfNum; i++, step++)
@@ -83,8 +83,9 @@ public class RatingView extends View {
for (int i = 0; i < emptyNum; i++, step++)
canvas.drawBitmap(EMPTY_START, step * mAWidth, 0, null);
}
public void setRating(float rating) {
mRating = Math.min(10, Math.round(rating * 2));
invalidate();
}
}
+4 -10
View File
@@ -24,6 +24,7 @@ import android.widget.Button;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.cardview.CardViewSalon;
import com.hippo.ehviewer.tile.TileSalon;
import com.hippo.ehviewer.util.Theme;
public class SuperButton extends Button {
@@ -45,13 +46,6 @@ public class SuperButton extends Button {
init(context, attrs, defStyle);
}
public static int getDarkerColor(int color) {
return ((int)((color & 0xff0000) * 0.8) & 0xff0000)
| ((int)((color & 0xff00) * 0.8) & 0xff00)
| ((int)((color & 0xff) * 0.8) & 0xff)
| (color & 0xff000000);
}
public void init(Context context, AttributeSet attrs, int defStyle) {
int backgroundType = BACKGROUND_TYPE_ROUND;
int bgColor = context.getResources().getColor(R.color.background_light);
@@ -92,8 +86,8 @@ public class SuperButton extends Button {
setRoundBackground(withShadow, new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{}}, new int[]{0xffcccccc, getDarkerColor(bgColor), bgColor},
boundColor == 0 ? null : new int[]{0xffcccccc, getDarkerColor(boundColor), boundColor}); // TODO
new int[]{}}, new int[]{0xffcccccc, Theme.getDarkerColor(bgColor), bgColor},
boundColor == 0 ? null : new int[]{0xffcccccc, Theme.getDarkerColor(boundColor), boundColor}); // TODO
}
private void setTileBackground(int[][] stateSets, int[] bgColors) {
@@ -104,6 +98,6 @@ public class SuperButton extends Button {
setTileBackground(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{}}, new int[]{0xffcccccc, getDarkerColor(bgColor), bgColor});
new int[]{}}, new int[]{0xffcccccc, Theme.getDarkerColor(bgColor), bgColor});
}
}
+22 -18
View File
@@ -16,6 +16,7 @@
package com.hippo.ehviewer.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
@@ -36,43 +37,46 @@ public class SuperToast extends Toast {
public static final int WARNING = 1;
public static final int ERROR = 2;
private final Context mContext;
private LinearLayout mMainView;
private ImageView mIcon;
private TextView mMessage;
public SuperToast(Context context) {
super(context);
mContext = context;
private static Context sContext;
public static void setContext(Context context) {
sContext = context;
}
public SuperToast() {
super(sContext);
init();
}
public SuperToast(Context context, int strResId) {
this(context);
public SuperToast(int strResId) {
this();
setMessage(strResId);
}
public SuperToast(Context context, String mesg) {
this(context);
public SuperToast(String mesg) {
this();
setMessage(mesg);
}
public SuperToast(Context context, int strResId, int type) {
this(context, strResId);
public SuperToast(int strResId, int type) {
this(strResId);
setTypeIcon(type);
}
public SuperToast(Context context, String mesg, int type) {
this(context, mesg);
public SuperToast(String mesg, int type) {
this(mesg);
setTypeIcon(type);
}
@SuppressLint("InflateParams")
private void init() {
LayoutInflater inflate = (LayoutInflater)
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FrameLayout view = (FrameLayout)inflate.inflate(R.layout.super_toast, null);
FrameLayout view = (FrameLayout)LayoutInflater.from(sContext)
.inflate(R.layout.super_toast, null);
mMainView = (LinearLayout)view.getChildAt(0);
// Set random color
mMainView.setBackgroundColor(Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor());
@@ -102,7 +106,7 @@ public class SuperToast extends Toast {
}
public SuperToast setIcon(int resId) {
return setIcon(mContext.getResources().getDrawable(resId));
return setIcon(sContext.getResources().getDrawable(resId));
}
public SuperToast setIcon(Drawable drawable) {
@@ -112,7 +116,7 @@ public class SuperToast extends Toast {
}
public SuperToast setMessage(int resId) {
return setMessage(mContext.getResources().getString(resId));
return setMessage(sContext.getResources().getString(resId));
}
public SuperToast setMessage(CharSequence text) {
@@ -0,0 +1,52 @@
/*
* 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.windowsanimate;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.AbsoluteLayout;
@SuppressWarnings("deprecation")
public class AnimateCanvas extends AbsoluteLayout {
private final List<Ripple> mRippleList = new LinkedList<Ripple>();
public AnimateCanvas(Context context) {
super(context);
setWillNotDraw(false);
}
void addRenderingRipple(Ripple ripple) {
if (!mRippleList.contains(ripple))
mRippleList.add(ripple);
}
void removeRenderingRipple(Ripple ripple) {
mRippleList.remove(ripple);
}
@Override
public void onDraw(Canvas canvas) {
for (Ripple ripple : mRippleList) {
ripple.draw(canvas);
}
}
}
@@ -0,0 +1,407 @@
/*
* 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.windowsanimate;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.hippo.ehviewer.util.MathUtils;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Utils;
/**
* @author Hippo
*
* Get lots of code from android.graphics.drawable.Ripple
*/
public class Ripple {
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final TimeInterpolator DECEL_INTERPOLATOR = new LogInterpolator();
private static final float GLOBAL_SPEED = 1.0F;
private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0F;
private static final float WAVE_TOUCH_UP_ACCELERATION = 3400.0F;
private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0F;
private static final float WAVE_OUTER_OPACITY_VELOCITY_MAX = 4.5F;
private static final float WAVE_OUTER_OPACITY_VELOCITY_MIN = 1.5F;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200.0F;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40.0F;
private static final long RIPPLE_ENTER_DELAY = 80L;
private final WindowsAnimate mWindowsAnimate;
private final View mView;
private final Rect mBounds;
private final boolean mkeepBound;
private float mOuterRadius;
private final int[] mStartPosition = new int[2];
private ObjectAnimator mAnimRadius;
private ObjectAnimator mAnimOpacity;
private ObjectAnimator mAnimOuterOpacity;
private ObjectAnimator mAnimX;
private ObjectAnimator mAnimY;
private float mOuterOpacity = 0.0F;
private float mOpacity = 1.0F;
private float mTweenRadius = 0.0F;
private float mTweenX = 0.0F;
private float mTweenY = 0.0F;
private static Paint mPaint;
static {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0x20444444);
}
public Ripple(WindowsAnimate windowsAnimate, View view, Rect bounds, boolean keepBound) {
mWindowsAnimate = windowsAnimate;
mView = view;
mBounds = new Rect(bounds);
mkeepBound = keepBound;
float halfWidth = mBounds.width() / 2.0F;
float halfHeight = mBounds.height() / 2.0F;
mOuterRadius = ((float) Math.sqrt(halfWidth * halfWidth
+ halfHeight * halfHeight));
}
public void onBoundsChanged(Rect bounds) {
mBounds.set(bounds);
float halfWidth = mBounds.width() / 2.0F;
float halfHeight = mBounds.height() / 2.0F;
mOuterRadius = ((float) Math.sqrt(halfWidth * halfWidth
+ halfHeight * halfHeight));
}
public void setOpacity(float a) {
mOpacity = a;
invalidateSelf();
}
public float getOpacity() {
return mOpacity;
}
public void setOuterOpacity(float a) {
mOuterOpacity = a;
invalidateSelf();
}
public float getOuterOpacity() {
return mOuterOpacity;
}
public void setRadiusGravity(float r) {
mTweenRadius = r;
invalidateSelf();
}
public float getRadiusGravity() {
return mTweenRadius;
}
public void setXGravity(float x) {
mTweenX = x;
invalidateSelf();
}
public float getXGravity() {
return mTweenX;
}
public void setYGravity(float y) {
mTweenY = y;
invalidateSelf();
}
public float getYGravity() {
return mTweenY;
}
// TODO make mkeepBound work, ripple only show int view's area, just use clipPath
public void draw(Canvas c) {
Utils.getCenterInWindows(mView, mStartPosition);
c.translate(mStartPosition[0], mStartPosition[1]);
drawSoftware(c, mPaint);
c.translate(-mStartPosition[0], -mStartPosition[1]);
}
private void drawSoftware(Canvas c, Paint p) {
int paintAlpha = p.getAlpha();
int outerAlpha = (int) (paintAlpha * mOuterOpacity + 0.5F);
if ((outerAlpha > 0) && (mOuterRadius > 0.0F)) {
p.setAlpha(outerAlpha);
p.setStyle(Paint.Style.FILL);
c.drawCircle(0.0F, 0.0F, mOuterRadius, p);
}
int alpha = (int) (paintAlpha * mOpacity + 0.5F);
float radius = MathUtils.lerp(0.0F, mOuterRadius,
mTweenRadius);
if ((alpha > 0) && (radius > 0.0F)) {
p.setAlpha(alpha);
p.setStyle(Paint.Style.FILL);
c.drawCircle(0.0F, 0.0F, radius, p);
}
p.setAlpha(paintAlpha);
}
// TODO Can't enter before exit end
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public void enter() {
addSelf();
mOuterOpacity = 0.0F;
mOpacity = 1.0F;
mTweenRadius = 0.0F;
mTweenX = 0.0F;
mTweenY = 0.0F;
int radiusDuration = (int) (1000.0D * Math.sqrt(mOuterRadius
/ WAVE_TOUCH_DOWN_ACCELERATION * Ui.mDensity) + 0.5D);
long outerDuration = 666L;
ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radiusGravity",
new float[] { 1.0F });
radius.setDuration(radiusDuration);
radius.setInterpolator(LINEAR_INTERPOLATOR);
radius.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity",
new float[] { 1.0F });
cX.setDuration(radiusDuration);
cX.setInterpolator(LINEAR_INTERPOLATOR);
cX.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity",
new float[] { 1.0F });
cY.setDuration(radiusDuration);
cY.setInterpolator(LINEAR_INTERPOLATOR);
cY.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity",
new float[] { 0.0F, 1.0F });
outer.setDuration(outerDuration);
outer.setInterpolator(LINEAR_INTERPOLATOR);
if (Build.VERSION.SDK_INT >= 18) {
radius.setAutoCancel(true);
cX.setAutoCancel(true);
cY.setAutoCancel(true);
outer.setAutoCancel(true);
}
mAnimRadius = radius;
mAnimOuterOpacity = outer;
mAnimX = cX;
mAnimY = cY;
radius.start();
outer.start();
cX.start();
cY.start();
}
public void exit() {
cancelSoftwareAnimations();
float radius = MathUtils.lerp(0.0F, mOuterRadius,
mTweenRadius);
float remaining;
if ((mAnimRadius != null) && (mAnimRadius.isRunning())) {
remaining = mOuterRadius - radius;
} else {
remaining = mOuterRadius;
}
int radiusDuration = (int) (1000.0D * Math.sqrt(remaining / 4424.0F
* Ui.mDensity) + 0.5D);
int opacityDuration = (int) (1000.0F * mOpacity / 3.0F + 0.5F);
float outerSizeInfluence = MathUtils.constrain(
(mOuterRadius - 40.0F * Ui.mDensity)
/ (200.0F * Ui.mDensity), 0.0F, 1.0F);
float outerOpacityVelocity = MathUtils.lerp(1.5F, 4.5F,
outerSizeInfluence);
int outerInflection = Math.max(0, (int) (1000.0F
* (mOpacity - mOuterOpacity)
/ (3.0F + outerOpacityVelocity) + 0.5F));
int inflectionOpacity = (int) (255.0F * (mOuterOpacity + outerInflection
* outerOpacityVelocity * outerSizeInfluence / 1000.0F) + 0.5F);
exitSoftware(radiusDuration, opacityDuration, outerInflection,
inflectionOpacity);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void exitSoftware(int radiusDuration, int opacityDuration,
int outerInflection, int inflectionOpacity) {
ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this,
"radiusGravity", new float[] { 1.0F });
radiusAnim.setDuration(radiusDuration);
radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity",
new float[] { 1.0F });
xAnim.setDuration(radiusDuration);
xAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity",
new float[] { 1.0F });
yAnim.setDuration(radiusDuration);
yAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity",
new float[] { 0.0F });
opacityAnim.setDuration(opacityDuration);
opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
ObjectAnimator outerOpacityAnim;
if (outerInflection > 0) {
outerOpacityAnim = ObjectAnimator.ofFloat(this,
"outerOpacity", new float[] { inflectionOpacity / 255.0F });
outerOpacityAnim.setDuration(outerInflection);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
final int outerDuration = opacityDuration - outerInflection;
if (outerDuration > 0) {
outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ObjectAnimator outerFadeOutAnim = ObjectAnimator
.ofFloat(Ripple.this, "outerOpacity",
new float[] { 0.0F });
if (Build.VERSION.SDK_INT >= 18)
outerFadeOutAnim.setAutoCancel(true);
outerFadeOutAnim.setDuration(outerDuration);
outerFadeOutAnim
.setInterpolator(Ripple.LINEAR_INTERPOLATOR);
outerFadeOutAnim
.addListener(Ripple.this.mAnimationListener);
Ripple.this.mAnimOuterOpacity = outerFadeOutAnim;
outerFadeOutAnim.start();
}
@Override
public void onAnimationCancel(Animator animation) {
animation.removeListener(this);
}
});
} else {
outerOpacityAnim.addListener(mAnimationListener);
}
} else {
outerOpacityAnim = ObjectAnimator.ofFloat(this, "outerOpacity",
new float[] { 0.0F });
outerOpacityAnim.setDuration(opacityDuration);
outerOpacityAnim.addListener(mAnimationListener);
}
if (Build.VERSION.SDK_INT >= 18) {
radiusAnim.setAutoCancel(true);
xAnim.setAutoCancel(true);
yAnim.setAutoCancel(true);
opacityAnim.setAutoCancel(true);
outerOpacityAnim.setAutoCancel(true);
}
mAnimRadius = radiusAnim;
mAnimOpacity = opacityAnim;
mAnimOuterOpacity = outerOpacityAnim;
mAnimX = opacityAnim;
mAnimY = opacityAnim;
radiusAnim.start();
opacityAnim.start();
outerOpacityAnim.start();
xAnim.start();
yAnim.start();
}
public void cancel() {
cancelSoftwareAnimations();
}
private void cancelSoftwareAnimations() {
if (mAnimRadius != null) {
mAnimRadius.cancel();
}
if (mAnimOpacity != null) {
mAnimOpacity.cancel();
}
if (mAnimOuterOpacity != null) {
mAnimOuterOpacity.cancel();
}
if (mAnimX != null) {
mAnimX.cancel();
}
if (mAnimY != null) {
mAnimY.cancel();
}
}
private void addSelf() {
mWindowsAnimate.addRenderingRipple(this);
}
private void removeSelf() {
mWindowsAnimate.removeRenderingRipple(this);
}
private void invalidateSelf() {
mWindowsAnimate.updateCanvas();
}
private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Ripple.this.removeSelf();
}
};
private static class LogInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
return 1.0F - (float) Math.pow(400.0D, -input * 1.4D);
}
}
}
@@ -0,0 +1,103 @@
/*
* 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.windowsanimate;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
/**
* @author Hippo
*
* Get lots of code from android.graphics.drawable.RippleDrawable
*/
public class RippleHelpDrawable extends Drawable {
private final Ripple mRipple;
private boolean mActive = false;
@SuppressWarnings("deprecation")
public RippleHelpDrawable(WindowsAnimate windowsAnimate, View view, boolean keepBound) {
mRipple = new Ripple(windowsAnimate, view, getBounds(), keepBound);
view.setBackgroundDrawable(this);
}
@Override
public boolean isStateful() {
return true;
}
@Override
protected boolean onStateChange(int[] stateSet) {
boolean active = false;
boolean enabled = false;
int N = stateSet.length;
for (int i = 0; i < N; i++) {
if (stateSet[i] == android.R.attr.state_enabled) {
enabled = true;
}
if ((stateSet[i] == android.R.attr.state_focused) ||
(stateSet[i] == android.R.attr.state_pressed)) {
active = true;
}
}
setActive((active) && (enabled));
return false;
}
private void setActive(boolean active) {
if (mActive != active) {
mActive = active;
if (active) {
mRipple.enter();
} else {
mRipple.exit();
}
}
}
@Override
protected void onBoundsChange(Rect bounds) {
mRipple.onBoundsChanged(bounds);
}
@Override
public void draw(Canvas canvas) {
// None
}
@Override
public void setAlpha(int alpha) {
// None
}
@Override
public void setColorFilter(ColorFilter cf) {
// None
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
}
@@ -0,0 +1,153 @@
/*
* 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.windowsanimate;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.AbsoluteLayout;
import com.hippo.ehviewer.drawable.OvalDrawable;
import com.hippo.ehviewer.util.Utils;
@SuppressWarnings("deprecation")
public final class WindowsAnimate {
private Context mContext;
private ViewGroup mContentViewGroup;
private AnimateCanvas mAnimateCanvas;
private int mRunningAnimateNum = 0;
public boolean init(Activity activity) {
mContentViewGroup = (ViewGroup)activity.getWindow().getDecorView()
.findViewById(android.R.id.content);
if (mContentViewGroup == null)
return false;
mContext = activity.getApplicationContext();
mAnimateCanvas = new AnimateCanvas(mContext);
mContentViewGroup.addView(mAnimateCanvas, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return true;
}
public void free() {
if (mContentViewGroup != null) {
mContentViewGroup.removeView(mAnimateCanvas);
mContentViewGroup = null;
}
}
public boolean isRunningAnimate() {
return mRunningAnimateNum != 0;
}
public void addRippleEffect(View view, boolean keepBound) {
new RippleHelpDrawable(this, view, keepBound);
}
public void removeRippleEffect(View view) {
// TODO
}
public void updateCanvas() {
mAnimateCanvas.invalidate();
}
void addRenderingRipple(Ripple ripple) {
mAnimateCanvas.addRenderingRipple(ripple);
}
void removeRenderingRipple(Ripple ripple) {
mAnimateCanvas.removeRenderingRipple(ripple);
}
public void addCircleTransitions(View view, int color, OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int[] loaction = new int[2];
Utils.getCenterInWindows(view, loaction);
addCircleTransitions(loaction[0], loaction[1], color, listener);
}
public void addCircleTransitions(View view, int x, int y, int color, OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int[] loaction = new int[2];
Utils.getLocationInWindow(view, loaction);
addCircleTransitions(loaction[0] + x, loaction[1] + y, color, listener);
}
public void addCircleTransitions(final int x, final int y, int color, final OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int maxWidth = mAnimateCanvas.getWidth();
int maxHeight = mAnimateCanvas.getHeight();
final double maxLength = Math.sqrt(maxWidth * maxWidth + maxHeight * maxHeight);
final View animateView = new View(mContext);
animateView.setClickable(true);
animateView.setBackgroundDrawable(new OvalDrawable(color));
final AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams(0, 0, x, y);
mAnimateCanvas.addView(animateView, lp);
ValueAnimator animation = ValueAnimator.ofFloat(0.0f, 1.0f);
animation.setDuration(500);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float scale = (Float)animation.getAnimatedValue();
lp.x = (int)(x - maxLength * scale);
lp.y = (int)(y - maxLength * scale);
lp.width = (int)(2 * maxLength * scale);
lp.height = (int)(2 * maxLength * scale);
animateView.requestLayout();
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
if (mAnimateCanvas != null)
mAnimateCanvas.removeView(animateView);
if (listener != null)
listener.onAnimationEnd();
mRunningAnimateNum--;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.setInterpolator(new AccelerateInterpolator());
animation.start();
mRunningAnimateNum++;
}
public interface OnAnimationEndListener {
public void onAnimationEnd();
}
}