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 000000000..e16f4bc7d Binary files /dev/null and b/res/drawable-hdpi/ic_reply.png differ diff --git a/res/drawable-mdpi/ic_reply.png b/res/drawable-mdpi/ic_reply.png new file mode 100644 index 000000000..213a147ee Binary files /dev/null and b/res/drawable-mdpi/ic_reply.png differ diff --git a/res/drawable-xhdpi/ic_reply.png b/res/drawable-xhdpi/ic_reply.png new file mode 100644 index 000000000..b9e9d5e43 Binary files /dev/null and b/res/drawable-xhdpi/ic_reply.png differ diff --git a/res/drawable-xxhdpi/ic_reply.png b/res/drawable-xxhdpi/ic_reply.png new file mode 100644 index 000000000..0782b8e80 Binary files /dev/null and b/res/drawable-xxhdpi/ic_reply.png differ diff --git a/res/layout/comments_item.xml b/res/layout/comments_item.xml index 1b05a1120..ec2c01e57 100644 --- a/res/layout/comments_item.xml +++ b/res/layout/comments_item.xml @@ -17,8 +17,8 @@ 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(); }