From 80282ffd0490562bfe0be49508376e2c7d4ea9dc Mon Sep 17 00:00:00 2001 From: seven332 Date: Wed, 6 Aug 2014 22:56:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AF=A6=E6=83=85=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project.properties | 1 + res/drawable-hdpi/ic_reply.png | Bin 0 -> 789 bytes res/drawable-mdpi/ic_reply.png | Bin 0 -> 519 bytes res/drawable-xhdpi/ic_reply.png | Bin 0 -> 893 bytes res/drawable-xxhdpi/ic_reply.png | Bin 0 -> 1614 bytes res/layout/comments_item.xml | 4 +- res/layout/gallery_detail.xml | 55 ++++- .../ehviewer/ui/GalleryDetailActivity.java | 216 ++++++++++++++++-- src/com/hippo/ehviewer/util/Theme.java | 9 +- src/com/hippo/ehviewer/util/Utils.java | 53 ----- src/com/hippo/ehviewer/util/ViewUtils.java | 94 ++++++++ .../hippo/ehviewer/widget/TagListView.java | 8 +- .../ehviewer/windowsanimate/RippleSprite.java | 4 +- .../windowsanimate/WindowsAnimate.java | 48 +++- 14 files changed, 392 insertions(+), 100 deletions(-) create mode 100644 res/drawable-hdpi/ic_reply.png create mode 100644 res/drawable-mdpi/ic_reply.png create mode 100644 res/drawable-xhdpi/ic_reply.png create mode 100644 res/drawable-xxhdpi/ic_reply.png create mode 100644 src/com/hippo/ehviewer/util/ViewUtils.java diff --git a/project.properties b/project.properties index 6d50dd21e..90d7efa9c 100644 --- a/project.properties +++ b/project.properties @@ -15,3 +15,4 @@ target=android-19 #proguard.config=E:/Android/android-sdk/tools/proguard/proguard-android.txt:proguard-project.txt android.library.reference.1=..\\..\\code\\SlidingMenu\\library android.library.reference.2=..\\..\\code\\SystemBarTint\\library +android.library.reference.3=../../code/FloatingActionButton/FloatingActionButton diff --git a/res/drawable-hdpi/ic_reply.png b/res/drawable-hdpi/ic_reply.png new file mode 100644 index 0000000000000000000000000000000000000000..e16f4bc7ddd64df7f0a1776c2a6c8ee9f2cdfb36 GIT binary patch literal 789 zcmV+w1M2*VP)Cj3CyD^bZ-eN0u-*{4^Y5zX~Sv zkeZ{un)+F=6D%lT_>T5r>|fXvG%f(b8zFHHyfvxuk+zkpgAuSWhvXb>yAbd=ssM;C zhrk1{1^fbcOnQ7aB2F3+i!wx&W}^t0k0!v7A2Xir^7u{VG?;?iA8b}omx$36QF;9k z&tKcf>v{0!3CI2>IMUA;o6GQ=`PSa|Gmw)=y|XdGHG*(iS{{=kq8Nxa_IA)X%GRa zoY$h&ZdowoqXf-U3aP2PJA#3t`00P;&1;0hRaOq+)$ZC=$)n{>Zg zDO9jYRpFzw(Iypye60xdL)z4iK);c9ih#-aaXRH44;p{lcyD9~IKUtmLH2A@MqXc4 zJAB^rwuNO~#4$H18+mIA^<&Og-iZf+d}#y_Fo8kYkvK2HFKHZUGUr_)par; z+3Pd#wnHCp)51ke1Ue3*%k$IV9s+(k^z$|iAt1=9vaS+e0Z*A&=XqWK6@s^kn}a}q zC4v;@*qt|!kAU1w3i6woXa?vStRNtlYh3{%Kf{=3GM-<scr=KkM|Z0IQ1{HfSTzu!F6`w-KVZ^ zQq2GcD!>*{EBZv6Xay55VJ1>D0K5mtje-Zf4>5s(*~|<8ZXtLFdQ)j1V{X!bl8IqV z9GOfc&Hx5h30y?e=oYP`Db%b1$1$**x&h!r1l>n%=o$^E+LxK<6!3(31OxA>8c^^p zf_7Jk-TbQ zV*{{!4`PRtfsnLULrzuN?_=pM8OQ=|T>=G{+D4^ab}sL`vD<5I!mM^47>ewHtl^O* z0N%?3dxlp{&*mi;qon=Orr}J_7&B0horjj7o^WFcFmT5W{qtI#Il13Y+O6L6xYGP7 z0S5etMN;#5;8$^hZST7nI3wspuycI&aV^KN(_npBUtnuM&iSGSm-9eQ!fq!z4-?}T z)5d_*yu`Y5fw6OeUep5rX}UNAt~*Nlywhoz6lPlAFpzr&z5&)0n;~g0Ir9Jj002ov JPDHLkV1hlL;+_Bi literal 0 HcmV?d00001 diff --git a/res/drawable-xhdpi/ic_reply.png b/res/drawable-xhdpi/ic_reply.png new file mode 100644 index 0000000000000000000000000000000000000000..b9e9d5e436e6ebba60509d31afd769fc8acf91a2 GIT binary patch literal 893 zcmV-@1A_dCP)p+lR&s-82>jc7y#Iw{Qs@$eBMZwB50MNs5it-GR9BC_(51m z0OUM>3IRXn1OQN2!%wmrJW)K^W0}#1{Y%bDw(;w6KBSI`aXzbs_i<}L{ zD}=pd{}zt@6%BxNwLeS3y-dS2&Ej>rrTuZ4-)gF zj`*PfNX5&7x6>f$8De?}l(HB!j^DtGTms7id4zor4aO-9X}kmw@Q7@RE^qS^oo1t) z-sYbjRwg!}}_O@E4 z03f%=YR#(y9BrQ!`GF6I5HIV8YV!ubaN>#dFF7#)2-fz#9UwD*oCWWG-Yl`CY-Rg7`Z}#yEE`82Iw;*=m4xLYSZaI5TF>{% z^E_*+zE^91(*O!>pZ=#O|L`o*5@#|_Qvga=`_%UGhiGFnKL@8N0P?7s)OBtHfXw`6 zlNr;FaR#8BP-x>-UI~Vluy#Hj0BxeNjn_FKwi(mTw{w6t(b&f891z=#Y3KU~Kg2mu TWEEWf00000NkvXXu0mjf*DjsX literal 0 HcmV?d00001 diff --git a/res/drawable-xxhdpi/ic_reply.png b/res/drawable-xxhdpi/ic_reply.png new file mode 100644 index 0000000000000000000000000000000000000000..0782b8e80a94b502b93eb68b2b98677ef72cc972 GIT binary patch literal 1614 zcmV-U2C?~xP)cet4{!n6XJCGQ{s63=1x^A7gWterumL?1$@T6CMC*A|MgD0CF zj`}3PeGqyPSR665Xb$)=cuS*mLN5fM_umDXmq!p^%<_H^?NvNsev0cSUNX}HK>Us{ za2r@Tk%`e6G#p(3UTcjEUc;D(wayiM6hBw=5@B~?L|c2$3o%wNc@PtFAtn*8hd(4#A{_nC`5#UBzrY(jYfP$!x!KL8ElHo{! z*ooj)FwN@dc*@-50t5!=)vNicwSF;u#DP=6mg3Se%n9dnZVf1I$c^K6HD%qAihPyR zSr353U8%o%{;DyAe8M@6`uYm z8FOej_ZgqsL4BP3KUTCAoxL*xgr2VeNWE13fSN&8Ok0QZD8gL_9)tWJs$QHje-;8H z2(qehqMpAo^!!GHte8rf3lPTqE2!+5piYn#(_W4FdPe98t4X(5NmBvBYG;m0od;q! z)?$b*%kwh_W$O{kF+Vo}nh3H+38bxz2dq{*qbg?aH1~kWJ6WmP zr(tIeybJkQGn-Le69Yc#u_{ z{A3>BLDqESClSDdtm(y7o}QW4cu zIb9H-(&K`VufGpi3-o79*{9qEs1#&{p0DTmJ3+pBN6rFN3bKaA{OpIFVYkdxfG@Su z0s7aGiSJ}V{!!%BK9K%4pi`-F0XoG-2P#{671V(?b*hRkfU#UIfD2&EfU$Y^02jcR z0b}#-0WN?s1IFgv16%-O28_+S2e<&n3>cet4{!mD889~Q9$+lMKPqPtf8EiFj{pDw M07*qoM6N<$f diff --git a/res/layout/gallery_detail.xml b/res/layout/gallery_detail.xml index 78d0789e4..18bc5be25 100644 --- a/res/layout/gallery_detail.xml +++ b/res/layout/gallery_detail.xml @@ -38,6 +38,7 @@ android:padding="16dp" > + + + + + + android:layout_marginTop="8dp" /> + android:layout_marginTop="8dp" /> + @@ -215,8 +221,8 @@ android:id="@+id/detail_rate" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:paddingTop="16dp" android:paddingBottom="16dp" + android:paddingTop="16dp" android:visibility="gone" > + - + + + + + + + + + android:textSize="24sp" /> \ No newline at end of file diff --git a/src/com/hippo/ehviewer/ui/GalleryDetailActivity.java b/src/com/hippo/ehviewer/ui/GalleryDetailActivity.java index 4702e36f8..86d2e87b7 100644 --- a/src/com/hippo/ehviewer/ui/GalleryDetailActivity.java +++ b/src/com/hippo/ehviewer/ui/GalleryDetailActivity.java @@ -16,28 +16,43 @@ package com.hippo.ehviewer.ui; +import java.util.List; + import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.ActionBar; +import android.app.Dialog; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.text.Html; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextSwitcher; import android.widget.TextView; import android.widget.ViewSwitcher; +import com.faizmalkani.floatingactionbutton.FloatingActionButton; import com.hippo.ehviewer.ImageLoader; import com.hippo.ehviewer.ListUrls; import com.hippo.ehviewer.R; @@ -56,7 +71,11 @@ 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.util.ViewUtils; +import com.hippo.ehviewer.widget.AlertButton; +import com.hippo.ehviewer.widget.DialogBuilder; import com.hippo.ehviewer.widget.FswView; +import com.hippo.ehviewer.widget.LinkifyTextView; import com.hippo.ehviewer.widget.LoadImageView; import com.hippo.ehviewer.widget.ProgressiveRatingBar; import com.hippo.ehviewer.widget.RefreshTextView; @@ -69,7 +88,8 @@ public class GalleryDetailActivity extends AbstractActivity implements View.OnClickListener, FswView.OnFitSystemWindowsListener, View.OnTouchListener , ViewSwitcher.ViewFactory, ProgressiveRatingBar.OnUserRateListener, PreviewList.PreviewHolder, - View.OnLayoutChangeListener { + View.OnLayoutChangeListener, AdapterView.OnItemClickListener, + AdapterView.OnItemLongClickListener { @SuppressWarnings("unused") private static final String TAG = GalleryDetailActivity.class.getSimpleName(); @@ -104,6 +124,7 @@ public class GalleryDetailActivity extends AbstractActivity private ScrollView mDetailScroll; private ScrollView mMoreDetailScroll; + private View mMoreComment; private View mDetailHeader; private View mDetailButtons; @@ -118,10 +139,17 @@ public class GalleryDetailActivity extends AbstractActivity private View mDividerCP; private LinearLayout mDetailPreview; + private ListView mCommentList; + private FloatingActionButton mReply; + private OvalDrawable mCategoryDrawable; private Drawable mRateDrawable; private Drawable mCheckmarkDrawable; + private Dialog mCommentLongClickDialog; + + private CommentAdapter mCommentAdapter; + private int mCurPreviewPage; private GalleryInfo handleIntent(Intent intent) { @@ -203,6 +231,7 @@ public class GalleryDetailActivity extends AbstractActivity // Get view mDetailScroll = (ScrollView)findViewById(R.id.detail_scroll); mMoreDetailScroll = (ScrollView)findViewById(R.id.more_detail_scroll); + mMoreComment = findViewById(R.id.more_comment); mRefreshText = (RefreshTextView)findViewById(R.id.refresh_text); mDetailHeader = findViewById(R.id.detail_header); @@ -234,6 +263,9 @@ public class GalleryDetailActivity extends AbstractActivity mPreview = (SimpleGridLayout)findViewById(R.id.preview); mPerviewPage = (SuperButton)findViewById(R.id.preview_num); + mCommentList = (ListView)findViewById(R.id.comment_list); + mReply = (FloatingActionButton)findViewById(R.id.reply); + // Get temp view FswView alignment = (FswView)findViewById(R.id.alignment); @@ -273,6 +305,7 @@ public class GalleryDetailActivity extends AbstractActivity mCommentMoreText.setTextColor(color); mPerviewPage.setRoundBackground(true, false, mResources.getColor(R.color.background_light), color); mPerviewPage.setTextColor(color); + mReply.setColor(color); // Set ripple mWindowsAnimate.addRippleEffect(mDownloadButton, true); @@ -292,8 +325,10 @@ public class GalleryDetailActivity extends AbstractActivity mFavorite.setOnClickListener(this); mRate.setOnClickListener(this); mDetailMore.setOnTouchListener(this); - mDetailPreview.setOnTouchListener(this); + mDetailComment.setOnTouchListener(this); mMoreDetailScroll.addOnLayoutChangeListener(this); + mCommentList.addOnLayoutChangeListener(this); + mReply.setOnClickListener(this); alignment.addOnFitSystemWindowsListener(this); doPreLayout(); @@ -303,11 +338,13 @@ public class GalleryDetailActivity extends AbstractActivity String detailUrl = mClient.getDetailUrl( mGalleryInfo.gid, mGalleryInfo.token); + mRefreshText.setRefreshing(true); + if (mGalleryInfo instanceof GalleryDetail) { GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo; if (galleryDetail.title == null) { - // TODO // We should get info from detail page + mClient.getGDetail(detailUrl, galleryDetail, new GDetailGetListener()); } else { mDetailScroll.setVisibility(View.VISIBLE); mDetailHeader.setVisibility(View.VISIBLE); @@ -373,12 +410,13 @@ public class GalleryDetailActivity extends AbstractActivity * ApiGalleryDetail */ private void doLayout() { - if (mDetailHeader.getVisibility() == View.GONE) { + if (mDetailScroll.getVisibility() == View.GONE) { // If not set header in doPreLayout + mDetailScroll.setVisibility(View.VISIBLE); 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)); + new LoadImageView.SimpleImageGetListener(mThumb)); mTitle.setText(mGalleryInfo.title); mUploader.setText(mGalleryInfo.uploader); } @@ -439,6 +477,10 @@ public class GalleryDetailActivity extends AbstractActivity i, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); } + mCommentAdapter = new CommentAdapter(); + mCommentList.setAdapter(mCommentAdapter); + mCommentList.setOnItemClickListener(this); + mCommentList.setOnItemLongClickListener(this); // Add preview if (galleryDetail.previewLists[0] != null) { @@ -459,8 +501,12 @@ public class GalleryDetailActivity extends AbstractActivity @SuppressLint("InflateParams") private View getCommentView(View contentView, Comment comment, boolean restrict) { - if (contentView == null) + if (contentView == null) { contentView = LayoutInflater.from(this).inflate(R.layout.comments_item, null); + if (!restrict) { + mWindowsAnimate.addRippleEffect(contentView, true); + } + } ((TextView)contentView.findViewById(R.id.user)).setText(comment.user); ((TextView)contentView.findViewById(R.id.time)).setText(comment.time); TextView commentText = (TextView)contentView.findViewById(R.id.comment); @@ -482,7 +528,10 @@ public class GalleryDetailActivity extends AbstractActivity super.onBackPressed(); } else if (mMoreDetailScroll.getVisibility() == View.VISIBLE) { mDetailScroll.setVisibility(View.VISIBLE); - mWindowsAnimate.addMoveTransitions(mMoreDetailScroll, null); + mWindowsAnimate.addMoveExitTransitions(mMoreDetailScroll, null); + } else if (mMoreComment.getVisibility() == View.VISIBLE) { + mDetailScroll.setVisibility(View.VISIBLE); + mWindowsAnimate.addMoveExitTransitions(mMoreComment, null); } } @@ -578,6 +627,41 @@ public class GalleryDetailActivity extends AbstractActivity }); animation.start(); mRunningAnimateNum++; + } else if (v == mReply) { + final EditText et = new EditText(this); + et.setGravity(Gravity.TOP); + et.setBackgroundDrawable(null); + new DialogBuilder(this).setTitle(R.string.reply).setView(et, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, 600), true).setSimpleNegativeButton() + .setPositiveButton(android.R.string.ok, new View.OnClickListener() { + @Override + public void onClick(View v) { + ((AlertButton)v).dialog.dismiss(); + mClient.comment(EhClient.getDetailUrl(mGalleryInfo.gid, + mGalleryInfo.token, 0, Config.getApiMode()), et.getText().toString(), + new EhClient.OnCommentListener() { + @Override + public void onSuccess(List comments) { + ((GalleryDetail)mGalleryInfo).comments = comments; + mCommentAdapter.notifyDataSetChanged(); + } + @Override + public void onFailure(String eMsg) { + new SuperToast(eMsg, SuperToast.WARNING).show(); + } + }); + } + }).create().show(); + } + } + + @Override + public void onLayoutChange(View v, int left, int top, int right, + int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (v == mMoreDetailScroll) { + mMoreDetailScroll.scrollTo(0, 0); + } else if (v == mCommentList) { + mCommentList.setSelection(0); } } @@ -586,15 +670,16 @@ public class GalleryDetailActivity extends AbstractActivity int paddingRight, int paddingBottom) { mDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); mMoreDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); + mCommentList.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom); + + ((FrameLayout.LayoutParams)mReply.getLayoutParams()).bottomMargin = Ui.dp2pix(16) + paddingBottom; } @Override @SuppressLint("ClickableViewAccessibility") public boolean onTouch(View v, MotionEvent event) { if (v == mDetailMore) { - // TODO bad idea to check click - if (event.getAction() == MotionEvent.ACTION_UP && - System.nanoTime() / 1000000 - event.getDownTime() < 200) { + if (ViewUtils.isClickAction(event)) { mWindowsAnimate.addCircleTransitions(mDetailMore, (int)event.getX(), (int)event.getY(), mResources.getColor(R.color.background_light), new WindowsAnimate.OnAnimationEndListener() { @@ -608,8 +693,33 @@ public class GalleryDetailActivity extends AbstractActivity } }); } - } else if (v == mDetailPreview) { - // TODO + } else if (v == mDetailComment) { + if (ViewUtils.isClickAction(event)) { + mWindowsAnimate.addCircleTransitions(mDetailComment, (int)event.getX(), + (int)event.getY(), mResources.getColor(R.color.background_light), + new WindowsAnimate.OnAnimationEndListener() { + @Override + public void onAnimationEnd() { + mDetailScroll.setVisibility(View.GONE); + mMoreComment.setVisibility(View.VISIBLE); + // Add reply icon animation + mReply.setVisibility(View.INVISIBLE); + AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f); + aa.setDuration(Constants.ANIMATE_TIME); + aa.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + @Override + public void onAnimationRepeat(Animation animation) {} + @Override + public void onAnimationEnd(Animation animation) { + mWindowsAnimate.addOvershootEnterTransitions(mReply, null); + } + }); + mMoreComment.startAnimation(aa); + } + }); + } } return true; } @@ -619,6 +729,53 @@ public class GalleryDetailActivity extends AbstractActivity mRatingText.setText(getRatingText(rating)); } + @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); + mCommentLongClickDialog = new DialogBuilder(this) + .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) { + mCommentLongClickDialog.dismiss(); + switch (position) { + case 0: + ClipboardManager cm = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(ClipData.newPlainText(null, c.comment)); + new SuperToast(R.string.copyed).show(); + break; + + case 1: + finish(); + Intent intent = new Intent(GalleryDetailActivity.this, 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; + } + } + }).setSimpleNegativeButton().create(); + mCommentLongClickDialog.show(); + return true; + } + @Override public View makeView() { TextView tv = new TextView(this); @@ -640,6 +797,7 @@ public class GalleryDetailActivity extends AbstractActivity implements EhClient.OnGetGDetailListener { @Override public void onSuccess(GalleryDetail md) { + mRefreshText.setRefreshing(false); doLayout(); } @@ -650,11 +808,35 @@ public class GalleryDetailActivity extends AbstractActivity } } - @Override - public void onLayoutChange(View v, int left, int top, int right, - int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - if (v == mMoreDetailScroll) { - mMoreDetailScroll.scrollTo(0, 0); + private class CommentAdapter extends BaseAdapter { + @Override + public int getCount() { + if (mGalleryInfo instanceof GalleryDetail) { + GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo; + if (galleryDetail.comments == null) + return 0; + else + return galleryDetail.comments.size(); + } else { + return 0; + } + } + + @Override + public Object getItem(int position) { + return ((GalleryDetail)mGalleryInfo).comments.get(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = getCommentView(convertView, + ((GalleryDetail)mGalleryInfo).comments.get(position), false); + return view; } } } diff --git a/src/com/hippo/ehviewer/util/Theme.java b/src/com/hippo/ehviewer/util/Theme.java index 180508e9e..7a0ac7caa 100644 --- a/src/com/hippo/ehviewer/util/Theme.java +++ b/src/com/hippo/ehviewer/util/Theme.java @@ -19,6 +19,7 @@ package com.hippo.ehviewer.util; import java.util.Random; import android.content.Context; +import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; @@ -60,10 +61,10 @@ public final class Theme { * @return */ 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); + float[] hsv = new float[3]; + Color.colorToHSV(color, hsv); + hsv[2] *= 0.8f; + return Color.HSVToColor(hsv); } public static StateListDrawable getClickDrawable(Context context, int color) { diff --git a/src/com/hippo/ehviewer/util/Utils.java b/src/com/hippo/ehviewer/util/Utils.java index 746c77cfe..7740a2cf4 100644 --- a/src/com/hippo/ehviewer/util/Utils.java +++ b/src/com/hippo/ehviewer/util/Utils.java @@ -30,12 +30,9 @@ import java.util.Locale; import android.annotation.SuppressLint; import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.Canvas; import android.os.AsyncTask; import android.os.Build; import android.view.View; -import android.view.ViewParent; public class Utils { @SuppressWarnings("unused") @@ -317,54 +314,4 @@ public class Utils { 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); - } - - /** - * Returns a bitmap showing a screenshot of the view passed in. - * @param v - * @return - */ - public static Bitmap getBitmapFromView(View v) { - Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(bitmap); - // TODO I need to know why I need it, when ScrollView - canvas.translate(-v.getScrollX(), -v.getScrollY()); - v.draw(canvas); - return bitmap; - } } diff --git a/src/com/hippo/ehviewer/util/ViewUtils.java b/src/com/hippo/ehviewer/util/ViewUtils.java new file mode 100644 index 000000000..0eb71cf66 --- /dev/null +++ b/src/com/hippo/ehviewer/util/ViewUtils.java @@ -0,0 +1,94 @@ +/* + * 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 android.graphics.Bitmap; +import android.graphics.Canvas; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewParent; + +public final class ViewUtils { + + /** + * Get view center location in window + * + * @param view + * @param location + */ + public static void getCenterInWindows(View view, int[] location) { + getLocationInWindow(view, location); + location[0] += view.getWidth() / 2; + location[1] += view.getHeight() / 2; + } + + /** + * Get view location in window + * + * @param view + * @param location + */ + 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); + } + + /** + * Returns a bitmap showing a screenshot of the view passed in. + * @param v + * @return + */ + public static Bitmap getBitmapFromView(View v) { + Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + // TODO I need to know why I need it, when ScrollView + canvas.translate(-v.getScrollX(), -v.getScrollY()); + v.draw(canvas); + return bitmap; + } + + public static boolean isClickAction(MotionEvent event) { + // TODO bad idea to check click + return event.getAction() == MotionEvent.ACTION_UP && + System.nanoTime() / 1000000 - event.getDownTime() < 200; + } +} diff --git a/src/com/hippo/ehviewer/widget/TagListView.java b/src/com/hippo/ehviewer/widget/TagListView.java index 392e219ce..c2446ec50 100644 --- a/src/com/hippo/ehviewer/widget/TagListView.java +++ b/src/com/hippo/ehviewer/widget/TagListView.java @@ -41,7 +41,7 @@ import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ListView; -import com.hippo.ehviewer.util.Utils; +import com.hippo.ehviewer.util.ViewUtils; /** * The dynamic listview is an extension of listview that supports cell dragging @@ -203,7 +203,7 @@ public class TagListView extends ListView { } private Bitmap getDeleteBitmap(View v) { - Bitmap bitmap = Utils.getBitmapFromView(v); + Bitmap bitmap = ViewUtils.getBitmapFromView(v); Canvas can = new Canvas(bitmap); Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); @@ -223,7 +223,7 @@ public class TagListView extends ListView { } private Bitmap getModifyBitmap(View v) { - Bitmap bitmap = Utils.getBitmapFromView(v); + Bitmap bitmap = ViewUtils.getBitmapFromView(v); Canvas can = new Canvas(bitmap); Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); @@ -236,7 +236,7 @@ public class TagListView extends ListView { /** Draws a black border over the screenshot of the view passed in. */ private Bitmap getHoverBitmap(View v) { - Bitmap bitmap = Utils.getBitmapFromView(v); + Bitmap bitmap = ViewUtils.getBitmapFromView(v); Canvas can = new Canvas(bitmap); Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); diff --git a/src/com/hippo/ehviewer/windowsanimate/RippleSprite.java b/src/com/hippo/ehviewer/windowsanimate/RippleSprite.java index 337eafee0..48ed67dc5 100644 --- a/src/com/hippo/ehviewer/windowsanimate/RippleSprite.java +++ b/src/com/hippo/ehviewer/windowsanimate/RippleSprite.java @@ -31,7 +31,7 @@ import android.view.animation.LinearInterpolator; import com.hippo.ehviewer.R; import com.hippo.ehviewer.util.MathUtils; import com.hippo.ehviewer.util.Ui; -import com.hippo.ehviewer.util.Utils; +import com.hippo.ehviewer.util.ViewUtils; /** * @author Hippo @@ -176,7 +176,7 @@ public class RippleSprite extends Sprite { @Override public void draw(Canvas c) { - Utils.getCenterInWindows(mView, mViewPosition); + ViewUtils.getCenterInWindows(mView, mViewPosition); int saved = c.save(); c.translate(mViewPosition[0], mViewPosition[1]); diff --git a/src/com/hippo/ehviewer/windowsanimate/WindowsAnimate.java b/src/com/hippo/ehviewer/windowsanimate/WindowsAnimate.java index da2100779..63455e861 100644 --- a/src/com/hippo/ehviewer/windowsanimate/WindowsAnimate.java +++ b/src/com/hippo/ehviewer/windowsanimate/WindowsAnimate.java @@ -26,14 +26,16 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; +import android.view.animation.OvershootInterpolator; import com.hippo.ehviewer.R; import com.hippo.ehviewer.util.Constants; -import com.hippo.ehviewer.util.Utils; +import com.hippo.ehviewer.util.ViewUtils; public final class WindowsAnimate implements View.OnTouchListener { private static final TimeInterpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator(); + private static final TimeInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(); private Context mContext; private ViewGroup mContentViewGroup; @@ -114,7 +116,7 @@ public final class WindowsAnimate throw new RuntimeException("Call init(Activity) first, or call it after call free()"); int[] loaction = new int[2]; - Utils.getCenterInWindows(view, loaction); + ViewUtils.getCenterInWindows(view, loaction); addCircleTransitions(loaction[0], loaction[1], color, listener); } @@ -132,7 +134,7 @@ public final class WindowsAnimate throw new RuntimeException("Call init(Activity) first, or call it after call free()"); int[] loaction = new int[2]; - Utils.getLocationInWindow(view, loaction); + ViewUtils.getLocationInWindow(view, loaction); addCircleTransitions(loaction[0] + x, loaction[1] + y, color, listener); } @@ -187,10 +189,10 @@ public final class WindowsAnimate * @param listener */ // TODO not just from left to right - public void addMoveTransitions(final View view, final OnAnimationEndListener listener) { + public void addMoveExitTransitions(final View view, final OnAnimationEndListener listener) { int[] location = new int[2]; - Utils.getLocationInWindow(view, location); - final BitmapSprite bs = new BitmapSprite(this, Utils.getBitmapFromView(view), location[0], location[1]); + ViewUtils.getLocationInWindow(view, location); + final BitmapSprite bs = new BitmapSprite(this, ViewUtils.getBitmapFromView(view), location[0], location[1]); ObjectAnimator oa = ObjectAnimator.ofInt(bs, "x", new int[] {location[0], mAnimateCanvas.getWidth()}); @@ -221,6 +223,40 @@ public final class WindowsAnimate mRunningAnimateNum++; } + public void addOvershootEnterTransitions(final View view, final OnAnimationEndListener listener) { + int[] location = new int[2]; + ViewUtils.getLocationInWindow(view, location); + final BitmapSprite bs = new BitmapSprite(this, ViewUtils.getBitmapFromView(view), location[0], mAnimateCanvas.getHeight()); + + ObjectAnimator oa = ObjectAnimator.ofInt(bs, "y", + new int[] {mAnimateCanvas.getHeight(), location[1]}); + oa.setDuration(Constants.ANIMATE_TIME); + oa.setInterpolator(OVERSHOOT_INTERPOLATOR); + oa.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + bs.addSelf(); + } + @Override + public void onAnimationRepeat(Animator animation) {} + @Override + public void onAnimationEnd(Animator animation) { + bs.removeSelf(); + bs.free(); + view.setVisibility(View.VISIBLE); + if (listener != null) + listener.onAnimationEnd(); + + mRunningAnimateNum--; + } + @Override + public void onAnimationCancel(Animator animation) {} + }); + oa.start(); + + mRunningAnimateNum++; + } + public interface OnAnimationEndListener { public void onAnimationEnd(); }