1
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/** 修复图片在ViewPager控件中缩放报错的BUG */
|
||||
public class HackyViewPager extends ViewPager {
|
||||
|
||||
public HackyViewPager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public HackyViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
try {
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.lzy.ninegrid.ImageInfo;
|
||||
import com.lzy.ninegrid.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ImagePreviewActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
|
||||
|
||||
public static final String IMAGE_INFO = "IMAGE_INFO";
|
||||
public static final String CURRENT_ITEM = "CURRENT_ITEM";
|
||||
public static final int ANIMATE_DURATION = 200;
|
||||
|
||||
private RelativeLayout rootView;
|
||||
|
||||
private ImagePreviewAdapter imagePreviewAdapter;
|
||||
private List<ImageInfo> imageInfo;
|
||||
private int currentItem;
|
||||
private int imageHeight;
|
||||
private int imageWidth;
|
||||
private int screenWidth;
|
||||
private int screenHeight;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_preview2);
|
||||
|
||||
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager2);
|
||||
final TextView tv_pager = (TextView) findViewById(R.id.tv_pager);
|
||||
rootView = (RelativeLayout) findViewById(R.id.rootView);
|
||||
|
||||
DisplayMetrics metric = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(metric);
|
||||
screenWidth = metric.widthPixels;
|
||||
screenHeight = metric.heightPixels;
|
||||
|
||||
Intent intent = getIntent();
|
||||
imageInfo = (List<ImageInfo>) intent.getSerializableExtra(IMAGE_INFO);
|
||||
currentItem = intent.getIntExtra(CURRENT_ITEM, 0);
|
||||
|
||||
imagePreviewAdapter = new ImagePreviewAdapter(this, imageInfo);
|
||||
viewPager.setAdapter(imagePreviewAdapter);
|
||||
viewPager.setCurrentItem(currentItem);
|
||||
viewPager.getViewTreeObserver().addOnPreDrawListener(this);
|
||||
viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
currentItem = position;
|
||||
tv_pager.setText(String.format(getString(R.string.select2), currentItem + 1, imageInfo.size()));
|
||||
}
|
||||
});
|
||||
tv_pager.setText(String.format(getString(R.string.select2), currentItem + 1, imageInfo.size()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
|
||||
finishActivityAnim();
|
||||
}
|
||||
|
||||
/** 绘制前开始动画 */
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
rootView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
final View view = imagePreviewAdapter.getPrimaryItem();
|
||||
final ImageView imageView = imagePreviewAdapter.getPrimaryImageView();
|
||||
computeImageWidthAndHeight(imageView);
|
||||
|
||||
final ImageInfo imageData = imageInfo.get(currentItem);
|
||||
final float vx = imageData.imageViewWidth * 1.0f / imageWidth;
|
||||
final float vy = imageData.imageViewHeight * 1.0f / imageHeight;
|
||||
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);
|
||||
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
long duration = animation.getDuration();
|
||||
long playTime = animation.getCurrentPlayTime();
|
||||
float fraction = duration > 0 ? (float) playTime / duration : 1f;
|
||||
if (fraction > 1) fraction = 1;
|
||||
view.setTranslationX(evaluateInt(fraction, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2, 0));
|
||||
view.setTranslationY(evaluateInt(fraction, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2, 0));
|
||||
view.setScaleX(evaluateFloat(fraction, vx, 1));
|
||||
view.setScaleY(evaluateFloat(fraction, vy, 1));
|
||||
view.setAlpha(fraction);
|
||||
rootView.setBackgroundColor(evaluateArgb(fraction, Color.TRANSPARENT, Color.BLACK));
|
||||
}
|
||||
});
|
||||
addIntoListener(valueAnimator);
|
||||
valueAnimator.setDuration(ANIMATE_DURATION);
|
||||
valueAnimator.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
/** activity的退场动画 */
|
||||
public void finishActivityAnim() {
|
||||
final View view = imagePreviewAdapter.getPrimaryItem();
|
||||
final ImageView imageView = imagePreviewAdapter.getPrimaryImageView();
|
||||
computeImageWidthAndHeight(imageView);
|
||||
|
||||
final ImageInfo imageData = imageInfo.get(currentItem);
|
||||
final float vx = imageData.imageViewWidth * 1.0f / imageWidth;
|
||||
final float vy = imageData.imageViewHeight * 1.0f / imageHeight;
|
||||
final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1.0f);
|
||||
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
long duration = animation.getDuration();
|
||||
long playTime = animation.getCurrentPlayTime();
|
||||
float fraction = duration > 0 ? (float) playTime / duration : 1f;
|
||||
if (fraction > 1) fraction = 1;
|
||||
view.setTranslationX(evaluateInt(fraction, 0, imageData.imageViewX + imageData.imageViewWidth / 2 - imageView.getWidth() / 2));
|
||||
view.setTranslationY(evaluateInt(fraction, 0, imageData.imageViewY + imageData.imageViewHeight / 2 - imageView.getHeight() / 2));
|
||||
view.setScaleX(evaluateFloat(fraction, 1, vx));
|
||||
view.setScaleY(evaluateFloat(fraction, 1, vy));
|
||||
view.setAlpha(1 - fraction);
|
||||
rootView.setBackgroundColor(evaluateArgb(fraction, Color.BLACK, Color.TRANSPARENT));
|
||||
}
|
||||
});
|
||||
addOutListener(valueAnimator);
|
||||
valueAnimator.setDuration(ANIMATE_DURATION);
|
||||
valueAnimator.start();
|
||||
}
|
||||
|
||||
/** 计算图片的宽高 */
|
||||
private void computeImageWidthAndHeight(ImageView imageView) {
|
||||
|
||||
// 获取真实大小
|
||||
try {
|
||||
Drawable drawable = imageView.getDrawable();
|
||||
int intrinsicHeight = drawable.getIntrinsicHeight();
|
||||
int intrinsicWidth = drawable.getIntrinsicWidth();
|
||||
// 计算出与屏幕的比例,用于比较以宽的比例为准还是高的比例为准,因为很多时候不是高度没充满,就是宽度没充满
|
||||
float h = screenHeight * 1.0f / intrinsicHeight;
|
||||
float w = screenWidth * 1.0f / intrinsicWidth;
|
||||
if (h > w) h = w;
|
||||
else w = h;
|
||||
|
||||
// 得出当宽高至少有一个充满的时候图片对应的宽高
|
||||
imageHeight = (int) (intrinsicHeight * h);
|
||||
imageWidth = (int) (intrinsicWidth * w);
|
||||
}catch (Exception e){
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** 进场动画过程监听 */
|
||||
private void addIntoListener(ValueAnimator valueAnimator) {
|
||||
valueAnimator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
rootView.setBackgroundColor(0x0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 退场动画过程监听 */
|
||||
private void addOutListener(ValueAnimator valueAnimator) {
|
||||
valueAnimator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
rootView.setBackgroundColor(0x0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
finish();
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Integer 估值器 */
|
||||
public Integer evaluateInt(float fraction, Integer startValue, Integer endValue) {
|
||||
int startInt = startValue;
|
||||
return (int) (startInt + fraction * (endValue - startInt));
|
||||
}
|
||||
|
||||
/** Float 估值器 */
|
||||
public Float evaluateFloat(float fraction, Number startValue, Number endValue) {
|
||||
float startFloat = startValue.floatValue();
|
||||
return startFloat + fraction * (endValue.floatValue() - startFloat);
|
||||
}
|
||||
|
||||
/** Argb 估值器 */
|
||||
public int evaluateArgb(float fraction, int startValue, int endValue) {
|
||||
int startA = (startValue >> 24) & 0xff;
|
||||
int startR = (startValue >> 16) & 0xff;
|
||||
int startG = (startValue >> 8) & 0xff;
|
||||
int startB = startValue & 0xff;
|
||||
|
||||
int endA = (endValue >> 24) & 0xff;
|
||||
int endR = (endValue >> 16) & 0xff;
|
||||
int endG = (endValue >> 8) & 0xff;
|
||||
int endB = endValue & 0xff;
|
||||
|
||||
return (startA + (int) (fraction * (endA - startA))) << 24//
|
||||
| (startR + (int) (fraction * (endR - startR))) << 16//
|
||||
| (startG + (int) (fraction * (endG - startG))) << 8//
|
||||
| (startB + (int) (fraction * (endB - startB)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.lzy.ninegrid.ImageInfo;
|
||||
import com.lzy.ninegrid.NineGridView;
|
||||
import com.lzy.ninegrid.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import uk.co.senab.photoview.PhotoView;
|
||||
import uk.co.senab.photoview.PhotoViewAttacher;
|
||||
|
||||
/**
|
||||
* ================================================
|
||||
* 作 者:廖子尧
|
||||
* 版 本:1.0
|
||||
* 创建日期:2016/3/21
|
||||
* 描 述:
|
||||
* 修订历史:
|
||||
* ================================================
|
||||
*/
|
||||
public class ImagePreviewAdapter extends PagerAdapter implements PhotoViewAttacher.OnPhotoTapListener {
|
||||
|
||||
private List<ImageInfo> imageInfo;
|
||||
private Context context;
|
||||
private View currentView;
|
||||
|
||||
public ImagePreviewAdapter(Context context, @NonNull List<ImageInfo> imageInfo) {
|
||||
super();
|
||||
this.imageInfo = imageInfo;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return imageInfo.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return view == object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
super.setPrimaryItem(container, position, object);
|
||||
currentView = (View) object;
|
||||
}
|
||||
|
||||
public View getPrimaryItem() {
|
||||
return currentView;
|
||||
}
|
||||
|
||||
public ImageView getPrimaryImageView() {
|
||||
return (ImageView) currentView.findViewById(R.id.pv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
View view = LayoutInflater.from(context).inflate(R.layout.item_photoview, container, false);
|
||||
|
||||
final ProgressBar pb = (ProgressBar) view.findViewById(R.id.pb);
|
||||
final PhotoView imageView = (PhotoView) view.findViewById(R.id.pv);
|
||||
|
||||
ImageInfo info = this.imageInfo.get(position);
|
||||
imageView.setOnPhotoTapListener(this);
|
||||
showExcessPic(info, imageView);
|
||||
|
||||
//如果需要加载的loading,需要自己改写,不能使用这个方法
|
||||
NineGridView.getImageLoader().onDisplayImage(view.getContext(), imageView, info.bigImageUrl);
|
||||
|
||||
// pb.setVisibility(View.VISIBLE);
|
||||
// Glide.with(context).load(info.bigImageUrl)//
|
||||
// .placeholder(R.drawable.ic_default_image)//
|
||||
// .error(R.drawable.ic_default_image)//
|
||||
// .diskCacheStrategy(DiskCacheStrategy.ALL)//
|
||||
// .listener(new RequestListener<String, GlideDrawable>() {
|
||||
// @Override
|
||||
// public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
|
||||
// pb.setVisibility(View.GONE);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
|
||||
// pb.setVisibility(View.GONE);
|
||||
// return false;
|
||||
// }
|
||||
// }).into(imageView);
|
||||
|
||||
container.addView(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
/** 展示过度图片 */
|
||||
private void showExcessPic(ImageInfo imageInfo, PhotoView imageView) {
|
||||
//先获取大图的缓存图片
|
||||
Bitmap cacheImage = NineGridView.getImageLoader().getCacheImage(imageInfo.bigImageUrl);
|
||||
//如果大图的缓存不存在,在获取小图的缓存
|
||||
if (cacheImage == null) cacheImage = NineGridView.getImageLoader().getCacheImage(imageInfo.thumbnailUrl);
|
||||
//如果没有任何缓存,使用默认图片,否者使用缓存
|
||||
if (cacheImage == null) {
|
||||
imageView.setImageResource(R.drawable.ic_default_color);
|
||||
} else {
|
||||
imageView.setImageBitmap(cacheImage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
container.removeView((View) object);
|
||||
}
|
||||
|
||||
/** 单击屏幕关闭 */
|
||||
@Override
|
||||
public void onPhotoTap(View view, float x, float y) {
|
||||
((ImagePreviewActivity) context).finishActivityAnim();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,601 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.pili.pldroid.player.IMediaController;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* You can write a custom MediaController instead of this class
|
||||
* A MediaController widget must implement all the interface defined by com.pili.pldroid.player.IMediaController
|
||||
*/
|
||||
public class MediaController extends FrameLayout implements IMediaController {
|
||||
|
||||
private static final String TAG = "PLMediaController";
|
||||
private IMediaController.MediaPlayerControl mPlayer;
|
||||
private Context mContext;
|
||||
private PopupWindow mWindow;
|
||||
private int mAnimStyle;
|
||||
private View mAnchor;
|
||||
private View mRoot;
|
||||
private ProgressBar mProgress;
|
||||
private TextView mEndTime, mCurrentTime;
|
||||
private long mDuration;
|
||||
private boolean mShowing;
|
||||
private boolean mDragging;
|
||||
private boolean mInstantSeeking = true;
|
||||
private long mSeekPosition = 0l;
|
||||
private static int sDefaultTimeout = 3000;
|
||||
private static final int SEEK_TO_POST_DELAY_MILLIS = 200;
|
||||
|
||||
private static final int FADE_OUT = 1;
|
||||
private static final int SHOW_PROGRESS = 2;
|
||||
private boolean mFromXml = false;
|
||||
private ImageButton mPauseButton;
|
||||
private ImageButton mFfwdButton;
|
||||
private ImageButton mRewButton;
|
||||
private ImageButton mNextButton;
|
||||
private ImageButton mPrevButton;
|
||||
|
||||
private boolean mUseFastForward;
|
||||
|
||||
private static final int IC_MEDIA_PAUSE_ID = Resources.getSystem().getIdentifier("ic_media_pause", "drawable", "android");
|
||||
private static final int IC_MEDIA_PLAY_ID = Resources.getSystem().getIdentifier("ic_media_play", "drawable", "android");
|
||||
private static final int MEDIA_CONTROLLER_ID = Resources.getSystem().getIdentifier("media_controller", "layout", "android");
|
||||
private static final int PRV_BUTTON_ID = Resources.getSystem().getIdentifier("prev", "id", "android");
|
||||
private static final int FFWD_BUTTON_ID = Resources.getSystem().getIdentifier("ffwd", "id", "android");
|
||||
private static final int NEXT_BUTTON_ID = Resources.getSystem().getIdentifier("next", "id", "android");
|
||||
private static final int REW_BUTTON_ID = Resources.getSystem().getIdentifier("rew", "id", "android");
|
||||
private static final int PAUSE_BUTTON_ID = Resources.getSystem().getIdentifier("pause", "id", "android");
|
||||
private static final int MEDIACONTROLLER_PROGRESS_ID = Resources.getSystem().getIdentifier("mediacontroller_progress", "id", "android");
|
||||
private static final int END_TIME_ID = Resources.getSystem().getIdentifier("time", "id", "android");
|
||||
private static final int CURRENT_TIME_ID = Resources.getSystem().getIdentifier("time_current", "id", "android");
|
||||
|
||||
private AudioManager mAM;
|
||||
private Runnable mLastSeekBarRunnable;
|
||||
private boolean mDisableProgress = false;
|
||||
private OnClickSpeedAdjustListener mOnClickSpeedAdjustListener;
|
||||
|
||||
public interface OnClickSpeedAdjustListener {
|
||||
void onClickNormal();
|
||||
void onClickFaster();
|
||||
void onClickSlower();
|
||||
}
|
||||
|
||||
public MediaController(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mRoot = this;
|
||||
mFromXml = true;
|
||||
initController(context);
|
||||
}
|
||||
|
||||
public MediaController(Context context) {
|
||||
super(context);
|
||||
if (!mFromXml && initController(context))
|
||||
initFloatingWindow();
|
||||
}
|
||||
|
||||
public MediaController(Context context, boolean useFastForward, boolean disableProgressBar) {
|
||||
this(context);
|
||||
mUseFastForward = useFastForward;
|
||||
mDisableProgress = disableProgressBar;
|
||||
}
|
||||
|
||||
public MediaController(Context context, boolean useFastForward) {
|
||||
this(context);
|
||||
mUseFastForward = useFastForward;
|
||||
}
|
||||
|
||||
public void refreshProgress() {
|
||||
mProgress.setProgress(1000);
|
||||
mCurrentTime.setText(generateTime(mDuration));
|
||||
}
|
||||
|
||||
public void setOnClickSpeedAdjustListener(OnClickSpeedAdjustListener listener) {
|
||||
mOnClickSpeedAdjustListener = listener;
|
||||
}
|
||||
|
||||
private boolean initController(Context context) {
|
||||
mUseFastForward = true;
|
||||
mContext = context.getApplicationContext();
|
||||
mAM = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInflate() {
|
||||
if (mRoot != null)
|
||||
initControllerView(mRoot);
|
||||
super.onFinishInflate();
|
||||
}
|
||||
|
||||
private void initFloatingWindow() {
|
||||
mWindow = new PopupWindow(mContext);
|
||||
mWindow.setFocusable(false);
|
||||
mWindow.setBackgroundDrawable(null);
|
||||
mWindow.setOutsideTouchable(true);
|
||||
mAnimStyle = android.R.style.Animation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the view that holds the widgets that control playback. Derived
|
||||
* classes can override this to create their own.
|
||||
*
|
||||
* @return The controller view.
|
||||
*/
|
||||
protected View makeControllerView() {
|
||||
return ((LayoutInflater) mContext
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(MEDIA_CONTROLLER_ID, this);
|
||||
}
|
||||
|
||||
private void initControllerView(View v) {
|
||||
// By default these are hidden.
|
||||
mPrevButton = (ImageButton) v.findViewById(PRV_BUTTON_ID);
|
||||
if (mPrevButton != null) {
|
||||
mPrevButton.setVisibility(View.GONE);
|
||||
}
|
||||
mNextButton = (ImageButton) v.findViewById(NEXT_BUTTON_ID);
|
||||
if (mNextButton != null) {
|
||||
mNextButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
mFfwdButton = (ImageButton) v.findViewById(FFWD_BUTTON_ID);
|
||||
if (mFfwdButton != null) {
|
||||
mFfwdButton.setOnClickListener(mFfwdListener);
|
||||
if (!mFromXml) {
|
||||
mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
mRewButton = (ImageButton) v.findViewById(REW_BUTTON_ID);
|
||||
if (mRewButton != null) {
|
||||
mRewButton.setOnClickListener(mRewListener);
|
||||
if (!mFromXml) {
|
||||
mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
mPauseButton = (ImageButton) v.findViewById(PAUSE_BUTTON_ID);
|
||||
if (mPauseButton != null) {
|
||||
mPauseButton.requestFocus();
|
||||
mPauseButton.setOnClickListener(mPauseListener);
|
||||
}
|
||||
|
||||
mProgress = (ProgressBar) v.findViewById(MEDIACONTROLLER_PROGRESS_ID);
|
||||
if (mProgress != null) {
|
||||
if (mProgress instanceof SeekBar) {
|
||||
SeekBar seeker = (SeekBar) mProgress;
|
||||
seeker.setOnSeekBarChangeListener(mSeekListener);
|
||||
seeker.setThumbOffset(1);
|
||||
}
|
||||
mProgress.setMax(1000);
|
||||
mProgress.setEnabled(!mDisableProgress);
|
||||
}
|
||||
|
||||
mEndTime = (TextView) v.findViewById(END_TIME_ID);
|
||||
mCurrentTime = (TextView) v.findViewById(CURRENT_TIME_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the action when the seekbar dragged by user
|
||||
*
|
||||
* @param seekWhenDragging
|
||||
* True the media will seek periodically
|
||||
*/
|
||||
public void setInstantSeeking(boolean seekWhenDragging) {
|
||||
mInstantSeeking = seekWhenDragging;
|
||||
}
|
||||
|
||||
private void disableUnsupportedButtons() {
|
||||
try {
|
||||
if (mPauseButton != null && !mPlayer.canPause())
|
||||
mPauseButton.setEnabled(false);
|
||||
} catch (IncompatibleClassChangeError ex) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Change the animation style resource for this controller.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If the controller is showing, calling this method will take effect only
|
||||
* the next time the controller is shown.
|
||||
* </p>
|
||||
*
|
||||
* @param animationStyle
|
||||
* animation style to use when the controller appears and disappears.
|
||||
* Set to -1 for the default animation, 0 for no animation,
|
||||
* or a resource identifier for an explicit animation.
|
||||
*
|
||||
*/
|
||||
public void setAnimationStyle(int animationStyle) {
|
||||
mAnimStyle = animationStyle;
|
||||
}
|
||||
|
||||
|
||||
public interface OnShownListener {
|
||||
public void onShown();
|
||||
}
|
||||
|
||||
private OnShownListener mShownListener;
|
||||
|
||||
public void setOnShownListener(OnShownListener l) {
|
||||
mShownListener = l;
|
||||
}
|
||||
|
||||
public interface OnHiddenListener {
|
||||
public void onHidden();
|
||||
}
|
||||
|
||||
private OnHiddenListener mHiddenListener;
|
||||
|
||||
public void setOnHiddenListener(OnHiddenListener l) {
|
||||
mHiddenListener = l;
|
||||
}
|
||||
|
||||
@SuppressLint("HandlerLeak")
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
long pos;
|
||||
switch (msg.what) {
|
||||
case FADE_OUT:
|
||||
hide();
|
||||
break;
|
||||
case SHOW_PROGRESS:
|
||||
if (!mPlayer.isPlaying()) {
|
||||
return;
|
||||
}
|
||||
pos = setProgress();
|
||||
if (pos == -1) {
|
||||
return;
|
||||
}
|
||||
if (!mDragging && mShowing) {
|
||||
msg = obtainMessage(SHOW_PROGRESS);
|
||||
sendMessageDelayed(msg, 50);
|
||||
updatePausePlay();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private long setProgress() {
|
||||
if (mPlayer == null || mDragging) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long position = mPlayer.getCurrentPosition();
|
||||
long duration = mPlayer.getDuration();
|
||||
if (mProgress != null) {
|
||||
if (duration > 0) {
|
||||
long pos = 1000L * position / duration;
|
||||
mProgress.setProgress((int) pos);
|
||||
}
|
||||
int percent = mPlayer.getBufferPercentage();
|
||||
mProgress.setSecondaryProgress(percent * 10);
|
||||
}
|
||||
|
||||
mDuration = duration;
|
||||
|
||||
if (mEndTime != null)
|
||||
mEndTime.setText(generateTime(mDuration));
|
||||
if (mCurrentTime != null)
|
||||
mCurrentTime.setText(generateTime(position));
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
private static String generateTime(long position) {
|
||||
int totalSeconds = (int) (position / 1000);
|
||||
|
||||
int seconds = totalSeconds % 60;
|
||||
int minutes = (totalSeconds / 60) % 60;
|
||||
int hours = totalSeconds / 3600;
|
||||
|
||||
if (hours > 0) {
|
||||
return String.format(Locale.US, "%02d:%02d:%02d", hours, minutes,
|
||||
seconds).toString();
|
||||
} else {
|
||||
return String.format(Locale.US, "%02d:%02d", minutes, seconds)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
show(sDefaultTimeout);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTrackballEvent(MotionEvent ev) {
|
||||
show(sDefaultTimeout);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
int keyCode = event.getKeyCode();
|
||||
if (event.getRepeatCount() == 0
|
||||
&& (keyCode == KeyEvent.KEYCODE_HEADSETHOOK
|
||||
|| keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE)) {
|
||||
doPauseResume();
|
||||
show(sDefaultTimeout);
|
||||
if (mPauseButton != null)
|
||||
mPauseButton.requestFocus();
|
||||
return true;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP) {
|
||||
if (mPlayer.isPlaying()) {
|
||||
mPlayer.pause();
|
||||
updatePausePlay();
|
||||
}
|
||||
return true;
|
||||
} else if (keyCode == KeyEvent.KEYCODE_BACK
|
||||
|| keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
hide();
|
||||
return true;
|
||||
} else {
|
||||
show(sDefaultTimeout);
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
private OnClickListener mPauseListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mOnClickSpeedAdjustListener != null) {
|
||||
mOnClickSpeedAdjustListener.onClickNormal();
|
||||
}
|
||||
doPauseResume();
|
||||
show(sDefaultTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
private void updatePausePlay() {
|
||||
if (mRoot == null || mPauseButton == null)
|
||||
return;
|
||||
|
||||
if (mPlayer.isPlaying())
|
||||
mPauseButton.setImageResource(IC_MEDIA_PAUSE_ID);
|
||||
else
|
||||
mPauseButton.setImageResource(IC_MEDIA_PLAY_ID);
|
||||
}
|
||||
|
||||
private void doPauseResume() {
|
||||
if (mPlayer.isPlaying())
|
||||
mPlayer.pause();
|
||||
else
|
||||
mPlayer.start();
|
||||
updatePausePlay();
|
||||
}
|
||||
|
||||
private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
|
||||
|
||||
public void onStartTrackingTouch(SeekBar bar) {
|
||||
mDragging = true;
|
||||
show(3600000);
|
||||
mHandler.removeMessages(SHOW_PROGRESS);
|
||||
if (mInstantSeeking)
|
||||
mAM.setStreamMute(AudioManager.STREAM_MUSIC, true);
|
||||
}
|
||||
|
||||
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
|
||||
if (!fromuser) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final long newposition = (long) (mDuration * progress) / 1000;
|
||||
String time = generateTime(newposition);
|
||||
if (mInstantSeeking) {
|
||||
mHandler.removeCallbacks(mLastSeekBarRunnable);
|
||||
mLastSeekBarRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mPlayer.seekTo(newposition);
|
||||
}
|
||||
};
|
||||
mHandler.postDelayed(mLastSeekBarRunnable, SEEK_TO_POST_DELAY_MILLIS);
|
||||
}
|
||||
if (mCurrentTime != null)
|
||||
mCurrentTime.setText(time);
|
||||
}
|
||||
|
||||
public void onStopTrackingTouch(SeekBar bar) {
|
||||
if (!mInstantSeeking)
|
||||
mPlayer.seekTo(mDuration * bar.getProgress() / 1000);
|
||||
|
||||
show(sDefaultTimeout);
|
||||
mHandler.removeMessages(SHOW_PROGRESS);
|
||||
mAM.setStreamMute(AudioManager.STREAM_MUSIC, false);
|
||||
mDragging = false;
|
||||
mHandler.sendEmptyMessageDelayed(SHOW_PROGRESS, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
private OnClickListener mRewListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mOnClickSpeedAdjustListener != null) {
|
||||
mOnClickSpeedAdjustListener.onClickSlower();
|
||||
}
|
||||
show(sDefaultTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
private OnClickListener mFfwdListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mOnClickSpeedAdjustListener != null) {
|
||||
mOnClickSpeedAdjustListener.onClickFaster();
|
||||
}
|
||||
show(sDefaultTimeout);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the view that acts as the anchor for the control view.
|
||||
*
|
||||
* - This can for example be a VideoView, or your Activity's main view.
|
||||
* - AudioPlayer has no anchor view, so the view parameter will be null.
|
||||
*
|
||||
* @param view
|
||||
* The view to which to anchor the controller when it is visible.
|
||||
*/
|
||||
@Override
|
||||
public void setAnchorView(View view) {
|
||||
mAnchor = view;
|
||||
if (mAnchor == null) {
|
||||
sDefaultTimeout = 0; // show forever
|
||||
}
|
||||
if (!mFromXml) {
|
||||
removeAllViews();
|
||||
mRoot = makeControllerView();
|
||||
mWindow.setContentView(mRoot);
|
||||
mWindow.setWidth(LayoutParams.MATCH_PARENT);
|
||||
mWindow.setHeight(LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
initControllerView(mRoot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMediaPlayer(MediaPlayerControl player) {
|
||||
mPlayer = player;
|
||||
updatePausePlay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
show(sDefaultTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the controller on screen. It will go away automatically after
|
||||
* 'timeout' milliseconds of inactivity.
|
||||
*
|
||||
* @param timeout
|
||||
* The timeout in milliseconds. Use 0 to show the controller until hide() is called.
|
||||
*/
|
||||
@Override
|
||||
public void show(int timeout) {
|
||||
if (!mShowing) {
|
||||
if (mAnchor != null && mAnchor.getWindowToken() != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
|
||||
}
|
||||
}
|
||||
if (mPauseButton != null)
|
||||
mPauseButton.requestFocus();
|
||||
disableUnsupportedButtons();
|
||||
|
||||
if (mFromXml) {
|
||||
setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
int[] location = new int[2];
|
||||
|
||||
if (mAnchor != null) {
|
||||
mAnchor.getLocationOnScreen(location);
|
||||
Rect anchorRect = new Rect(location[0], location[1],
|
||||
location[0] + mAnchor.getWidth(), location[1]
|
||||
+ mAnchor.getHeight());
|
||||
|
||||
mWindow.setAnimationStyle(mAnimStyle);
|
||||
mWindow.showAtLocation(mAnchor, Gravity.BOTTOM,
|
||||
anchorRect.left, 0);
|
||||
} else {
|
||||
Rect anchorRect = new Rect(location[0], location[1],
|
||||
location[0] + mRoot.getWidth(), location[1]
|
||||
+ mRoot.getHeight());
|
||||
|
||||
mWindow.setAnimationStyle(mAnimStyle);
|
||||
mWindow.showAtLocation(mRoot, Gravity.BOTTOM,
|
||||
anchorRect.left, 0);
|
||||
}
|
||||
}
|
||||
mShowing = true;
|
||||
if (mShownListener != null)
|
||||
mShownListener.onShown();
|
||||
}
|
||||
updatePausePlay();
|
||||
mHandler.sendEmptyMessage(SHOW_PROGRESS);
|
||||
|
||||
if (timeout != 0) {
|
||||
mHandler.removeMessages(FADE_OUT);
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(FADE_OUT),
|
||||
timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShowing() {
|
||||
return mShowing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if (mShowing) {
|
||||
if (mAnchor != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
//mAnchor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
|
||||
}
|
||||
}
|
||||
try {
|
||||
mHandler.removeMessages(SHOW_PROGRESS);
|
||||
if (mFromXml)
|
||||
setVisibility(View.GONE);
|
||||
else
|
||||
mWindow.dismiss();
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Log.d(TAG, "MediaController already removed");
|
||||
}
|
||||
mShowing = false;
|
||||
if (mHiddenListener != null)
|
||||
mHiddenListener.onHidden();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
if (mPauseButton != null) {
|
||||
mPauseButton.setEnabled(enabled);
|
||||
}
|
||||
if (mFfwdButton != null) {
|
||||
mFfwdButton.setEnabled(enabled);
|
||||
}
|
||||
if (mRewButton != null) {
|
||||
mRewButton.setEnabled(enabled);
|
||||
}
|
||||
if (mProgress != null && !mDisableProgress)
|
||||
mProgress.setEnabled(enabled);
|
||||
disableUnsupportedButtons();
|
||||
super.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public PopupWindow getWindow() {
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
public long getSeekPosition() {
|
||||
return mSeekPosition;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import com.lzy.ninegrid.ImageInfo;
|
||||
import com.lzy.ninegrid.NineGridView;
|
||||
import com.lzy.ninegrid.NineGridViewAdapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ================================================
|
||||
* 作 者:廖子尧
|
||||
* 版 本:1.0
|
||||
* 创建日期:2016/3/21
|
||||
* 描 述:
|
||||
* 修订历史:
|
||||
* ================================================
|
||||
*/
|
||||
public class NineGridViewClickAdapter extends NineGridViewAdapter {
|
||||
|
||||
private int statusHeight;
|
||||
|
||||
public NineGridViewClickAdapter(Context context, List<ImageInfo> imageInfo) {
|
||||
super(context, imageInfo);
|
||||
statusHeight = getStatusHeight(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onImageItemClick(Context context, NineGridView nineGridView, int index, List<ImageInfo> imageInfo) {
|
||||
if (imageInfo.get(index).type == 2) {
|
||||
Intent intent = new Intent(context, VideoPreviewActivity.class);
|
||||
intent.putExtra("url", imageInfo.get(index).bigImageUrl);
|
||||
context.startActivity(intent);
|
||||
}else {
|
||||
for (int i = 0; i < imageInfo.size(); i++) {
|
||||
ImageInfo info = imageInfo.get(i);
|
||||
View imageView;
|
||||
if (i < nineGridView.getMaxSize()) {
|
||||
imageView = nineGridView.getChildAt(i);
|
||||
} else {
|
||||
//如果图片的数量大于显示的数量,则超过部分的返回动画统一退回到最后一个图片的位置
|
||||
imageView = nineGridView.getChildAt(nineGridView.getMaxSize() - 1);
|
||||
}
|
||||
info.imageViewWidth = imageView.getWidth();
|
||||
info.imageViewHeight = imageView.getHeight();
|
||||
int[] points = new int[2];
|
||||
imageView.getLocationInWindow(points);
|
||||
info.imageViewX = points[0];
|
||||
info.imageViewY = points[1] - statusHeight;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, ImagePreviewActivity.class);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(ImagePreviewActivity.IMAGE_INFO, (Serializable) imageInfo);
|
||||
bundle.putInt(ImagePreviewActivity.CURRENT_ITEM, index);
|
||||
intent.putExtras(bundle);
|
||||
context.startActivity(intent);
|
||||
((Activity) context).overridePendingTransition(0, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得状态栏的高度
|
||||
*/
|
||||
public int getStatusHeight(Context context) {
|
||||
int statusHeight = -1;
|
||||
try {
|
||||
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
|
||||
Object object = clazz.newInstance();
|
||||
int height = Integer.parseInt(clazz.getField("status_bar_height").get(object).toString());
|
||||
statusHeight = context.getResources().getDimensionPixelSize(height);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return statusHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.lzy.ninegrid.preview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.lzy.ninegrid.R;
|
||||
import com.pili.pldroid.player.widget.PLVideoView;
|
||||
|
||||
public class VideoPreviewActivity extends Activity {
|
||||
|
||||
private PLVideoView pLVideoView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_preview_video);
|
||||
pLVideoView = findViewById(R.id.pLVideoView);
|
||||
String url = getIntent().getStringExtra("url");
|
||||
pLVideoView.setVideoPath(url);
|
||||
MediaController mMediaController = new MediaController(this);
|
||||
pLVideoView.setMediaController(mMediaController);
|
||||
pLVideoView.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
pLVideoView.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
pLVideoView.pause();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
pLVideoView.stopPlayback();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user