Commit cce84b56 by fengquan

feat: 咨询师图片/视频预览

parent cea87958
......@@ -23,6 +23,8 @@ import com.ydl.ydlcommon.utils.AppProgressUtils;
import com.ydl.ydlcommon.utils.Utils;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.common.tools.ToastUtil;
import com.yidianling.consultant.preview.TestImageLoader;
import com.yidianling.consultant.preview.ZoomMediaLoader;
import com.yidianling.course.lifeCallback.CoursePlayLifecycle;
......@@ -48,7 +50,7 @@ public class ComponentTestApp extends BaseApp {
com.ydl.ydlcommon.utils.LogUtil.debug = BuildConfig.DEBUG;
webviewSetPath(this);
ZoomMediaLoader.getInstance().init(new TestImageLoader());
if (!BuildConfig.DEBUG && Build.VERSION.SDK_INT == Build.VERSION_CODES.P) {//release包去除,debug包不去除,用于检测是否还有反射api的方法
//去掉在Android P上的提醒弹窗 Detected problems with API
......
......@@ -70,6 +70,7 @@ dependencies {
kapt 'com.alibaba:arouter-compiler:1.2.2'
implementation rootProject.ext.dependencies["BaseRecyclerViewAdapterHelper"]
api rootProject.ext.dependencies["ydl-user-router"]
implementation "com.ydl:jjdxm-ijkplayer:0.0.33"
if (rootProject.ext.dev_mode){
//开发时使用
implementation modularPublication('com.ydl:m-user-api')
......
......@@ -18,6 +18,13 @@
android:name=".ConsultAssistantCenterActivity"
android:screenOrientation="portrait"
android:theme="@style/consultant_Transparent"/>
<activity android:name=".preview.GridPreviewActivity"
android:screenOrientation="portrait"
android:theme="@style/consultant_Transparent"/>
<activity android:name=".preview.GPreviewActivity"
android:screenOrientation="portrait"
android:theme="@style/consultant_Transparent"/>
</application>
</manifest>
\ No newline at end of file
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.annotation.TargetApi;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.MotionEvent;
import android.view.View;
/**
* @author rainb
*/
public class Compat {
private static final int SIXTY_FPS_INTERVAL = 1000 / 60;
public static void postOnAnimation(View view, Runnable runnable) {
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
postOnAnimationJellyBean(view, runnable);
} else {
view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
}
}
@TargetApi(16)
private static void postOnAnimationJellyBean(View view, Runnable runnable) {
view.postOnAnimation(runnable);
}
public static int getPointerIndex(int action) {
if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB)
return getPointerIndexHoneyComb(action);
else
return getPointerIndexEclair(action);
}
@SuppressWarnings("deprecation")
@TargetApi(VERSION_CODES.ECLAIR)
private static int getPointerIndexEclair(int action) {
return (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
}
@TargetApi(VERSION_CODES.HONEYCOMB)
private static int getPointerIndexHoneyComb(int action) {
return (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
/**
* @author rainb
*/
public class CupcakeGestureDetector implements GestureDetector {
protected OnGestureListener mListener;
private static final String LOG_TAG = "CupcakeGestureDetector";
float mLastTouchX;
float mLastTouchY;
final float mTouchSlop;
final float mMinimumVelocity;
@Override
public void setOnGestureListener(OnGestureListener listener) {
this.mListener = listener;
}
public CupcakeGestureDetector(Context context) {
final ViewConfiguration configuration = ViewConfiguration
.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mTouchSlop = configuration.getScaledTouchSlop();
}
private VelocityTracker mVelocityTracker;
private boolean mIsDragging;
float getActiveX(MotionEvent ev) {
return ev.getX();
}
float getActiveY(MotionEvent ev) {
return ev.getY();
}
@Override
public boolean isScaling() {
return false;
}
@Override
public boolean isDragging() {
return mIsDragging;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mVelocityTracker = VelocityTracker.obtain();
if (null != mVelocityTracker) {
mVelocityTracker.addMovement(ev);
} else {
Log.i(LOG_TAG, "Velocity tracker is null");
}
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
mIsDragging = false;
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = getActiveX(ev);
final float y = getActiveY(ev);
final float dx = x - mLastTouchX, dy = y - mLastTouchY;
if (!mIsDragging) {
// Use Pythagoras to see if drag length is larger than
// touch slop
mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
}
if (mIsDragging) {
mListener.onDrag(dx, dy);
mLastTouchX = x;
mLastTouchY = y;
if (null != mVelocityTracker) {
mVelocityTracker.addMovement(ev);
}
}
break;
}
case MotionEvent.ACTION_CANCEL: {
// Recycle Velocity Tracker
if (null != mVelocityTracker) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
}
case MotionEvent.ACTION_UP: {
if (mIsDragging) {
if (null != mVelocityTracker) {
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
// Compute velocity within the last 1000ms
mVelocityTracker.addMovement(ev);
mVelocityTracker.computeCurrentVelocity(1000);
final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker
.getYVelocity();
// If the velocity is greater than minVelocity, call
// listener
if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
mListener.onFling(mLastTouchX, mLastTouchY, -vX,
-vY);
}
}
}
// Recycle Velocity Tracker
if (null != mVelocityTracker) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
break;
}
}
return true;
}
}
package com.yidianling.consultant.preview;
import android.graphics.RectF;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.ImageView;
/**
* @author rainb
*/
public class DefaultOnDoubleTapListener implements GestureDetector.OnDoubleTapListener {
private PhotoViewAttacher photoViewAttacher;
/**
* Default constructor
*
* @param photoViewAttacher PhotoViewAttacher to bind to
*/
public DefaultOnDoubleTapListener(PhotoViewAttacher photoViewAttacher) {
setPhotoViewAttacher(photoViewAttacher);
}
/**
* Allows to change PhotoViewAttacher within range of single instance
*
* @param newPhotoViewAttacher PhotoViewAttacher to bind to
*/
public void setPhotoViewAttacher(PhotoViewAttacher newPhotoViewAttacher) {
this.photoViewAttacher = newPhotoViewAttacher;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (this.photoViewAttacher == null) {
return false;
}
ImageView imageView = photoViewAttacher.getImageView();
if (null != photoViewAttacher.getOnPhotoTapListener()) {
final RectF displayRect = photoViewAttacher.getDisplayRect();
if (null != displayRect) {
final float x = e.getX(), y = e.getY();
// Check to see if the user tapped on the photo
if (displayRect.contains(x, y)) {
float xResult = (x - displayRect.left)
/ displayRect.width();
float yResult = (y - displayRect.top)
/ displayRect.height();
photoViewAttacher.getOnPhotoTapListener().onPhotoTap(imageView, xResult, yResult);
return true;
} else {
photoViewAttacher.getOnPhotoTapListener().onOutsidePhotoTap();
}
}
}
if (null != photoViewAttacher.getOnViewTapListener()) {
photoViewAttacher.getOnViewTapListener().onViewTap(imageView, e.getX(), e.getY());
}
return false;
}
@Override
public boolean onDoubleTap(MotionEvent ev) {
if (photoViewAttacher == null) {
return false;
}
try {
float scale = photoViewAttacher.getScale();
float x = ev.getX();
float y = ev.getY();
if (scale < photoViewAttacher.getMediumScale()) {
photoViewAttacher.setScale(photoViewAttacher.getMediumScale(), x, y, true);
} else if (scale >= photoViewAttacher.getMediumScale() && scale < photoViewAttacher.getMaximumScale()) {
photoViewAttacher.setScale(photoViewAttacher.getMaximumScale(), x, y, true);
} else {
photoViewAttacher.setScale(photoViewAttacher.getMinimumScale(), x, y, true);
}
} catch (ArrayIndexOutOfBoundsException e) {
// Can sometimes happen when getX() and getY() is called
}
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// Wait for the confirmed onDoubleTap() instead
return false;
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.yidianling.consultant.preview;
import android.annotation.TargetApi;
import android.content.Context;
import android.view.MotionEvent;
/**
* @author rainb
*/
@TargetApi(5)
public class EclairGestureDetector extends CupcakeGestureDetector {
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private int mActivePointerIndex = 0;
public EclairGestureDetector(Context context) {
super(context);
}
@Override
float getActiveX(MotionEvent ev) {
try {
return ev.getX(mActivePointerIndex);
} catch (Exception e) {
return ev.getX();
}
}
@Override
float getActiveY(MotionEvent ev) {
try {
return ev.getY(mActivePointerIndex);
} catch (Exception e) {
return ev.getY();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
// Ignore deprecation, ACTION_POINTER_ID_MASK and
// ACTION_POINTER_ID_SHIFT has same value and are deprecated
// You can have either deprecation or lint target api warning
final int pointerIndex = Compat.getPointerIndex(ev.getAction());
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
}
break;
}
mActivePointerIndex = ev
.findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId
: 0);
try {
return super.onTouchEvent(ev);
} catch (IllegalArgumentException e) {
// Fix for support lib bug, happening when onDestroy is
return true;
}
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
* <p/>
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.yidianling.consultant.preview;
import android.annotation.TargetApi;
import android.content.Context;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
/**
* @author rainb
*/
@TargetApi(8)
public class FroyoGestureDetector extends EclairGestureDetector {
protected final ScaleGestureDetector mDetector;
public FroyoGestureDetector(Context context) {
super(context);
ScaleGestureDetector.OnScaleGestureListener mScaleListener = new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactor = detector.getScaleFactor();
if (Float.isNaN(scaleFactor) || Float.isInfinite(scaleFactor)) {
return false;
}
mListener.onScale(scaleFactor,
detector.getFocusX(), detector.getFocusY());
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
// NO-OP
}
};
mDetector = new ScaleGestureDetector(context, mScaleListener);
}
@Override
public boolean isScaling() {
return mDetector.isInProgress();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
try {
mDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
} catch (IllegalArgumentException e) {
// Fix for support lib bug, happening when onDestroy is
return true;
}
}
}
package com.yidianling.consultant.preview;
import android.graphics.Color;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import com.yidianling.consultant.R;
import java.util.ArrayList;
import java.util.List;
/**
* @author rainb
*/
public class GPreviewActivity extends AppCompatActivity {
protected boolean isTransformOut = false;
/*** 图片的地址***/
private List<IThumbViewInfo> imgUrls;
/*** 当前图片的位置 ***/
protected int currentIndex;
/***指示器类型枚举***/
private GPreviewBuilder.IndicatorType type;
/***默认显示***/
private boolean isShow = true;
/*** 展示图片的viewPager ***/
private PhotoViewPager viewPager;
/*** 图片的展示的Fragment***/
private List<BasePhotoFragment> fragments = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
setContentView(R.layout.consultant_image_preview_photo);
initView();
}
private void initView() {
viewPager = findViewById(R.id.viewPager);
//viewPager的适配器
PhotoPagerAdapter adapter = new PhotoPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(currentIndex);
// viewPager.setOffscreenPageLimit(3);
viewPager.setOffscreenPageLimit(0);
}
private void initData() {
imgUrls = getIntent().getParcelableArrayListExtra("imagePaths");
currentIndex = getIntent().getIntExtra("position", -1);
type = (GPreviewBuilder.IndicatorType) getIntent().getSerializableExtra("type");
isShow = getIntent().getBooleanExtra("isShow", true);
boolean isFullscreen = getIntent().getBooleanExtra("isFullscreen", false);
boolean isScale = getIntent().getBooleanExtra("isScale", false);
SmoothImageView.setFullscreen(isFullscreen);
SmoothImageView.setIsScale(isScale);
if (isFullscreen) {
setTheme(android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
}
initFragment(imgUrls, currentIndex, BasePhotoFragment.class);
}
private void initFragment(List<IThumbViewInfo> imgUrls, int currentIndex, Class<BasePhotoFragment> className) {
if (imgUrls != null) {
int size = imgUrls.size();
for (int i = 0; i < size; i++) {
fragments.add(BasePhotoFragment.
getInstance(className, imgUrls.get(i),
currentIndex == i,
getIntent().getBooleanExtra("isSingleFling", false),
getIntent().getBooleanExtra("isDrag", false),
getIntent().getFloatExtra("sensitivity", 0.5f))
);
}
} else {
finish();
}
}
@Override
protected void onDestroy() {
ZoomMediaLoader.getInstance().getLoader().clearMemory(this);
if (viewPager != null) {
viewPager.setAdapter(null);
viewPager.clearOnPageChangeListeners();
viewPager.removeAllViews();
viewPager = null;
}
if (fragments != null) {
fragments.clear();
fragments = null;
}
if (imgUrls != null) {
imgUrls.clear();
imgUrls = null;
}
super.onDestroy();
}
/***
* 得到PhotoViewPager
* @return PhotoViewPager
* **/
public PhotoViewPager getViewPager() {
return viewPager;
}
public void transformOut() {
if (isTransformOut) {
return;
}
getViewPager().setEnabled(false);
isTransformOut = true;
int currentItem = viewPager.getCurrentItem();
if (currentItem < imgUrls.size()) {
BasePhotoFragment fragment = fragments.get(currentItem);
fragment.changeBg(Color.TRANSPARENT);
fragment.transformOut(new SmoothImageView.onTransformListener() {
@Override
public void onTransformCompleted(SmoothImageView.Status status) {
getViewPager().setEnabled(true);
exit();
}
});
} else {
exit();
}
}
/**
* 关闭页面
*/
private void exit() {
finish();
overridePendingTransition(0, 0);
}
@Override
public void onBackPressed() {
isTransformOut = false;
transformOut();
}
@Override
public void finish() {
// BasePhotoFragment.listener=null;
super.finish();
}
/**
* pager的适配器
*/
private class PhotoPagerAdapter extends FragmentStatePagerAdapter {
PhotoPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments == null ? 0 : fragments.size();
}
}
}
package com.yidianling.consultant.preview;
import android.app.Activity;
import android.content.Intent;
import android.os.Parcelable;
import androidx.fragment.app.Fragment;
import java.util.ArrayList;
import java.util.List;
/**
* @author rainb
*/
public class GPreviewBuilder {
private Activity mContext;
private Intent intent;
private Class className;
private GPreviewBuilder(Activity activity) {
mContext = activity;
intent = new Intent();
}
public static GPreviewBuilder form(Activity activity) {
return new GPreviewBuilder(activity);
}
public static GPreviewBuilder from(Fragment fragment) {
return new GPreviewBuilder(fragment.getActivity());
}
/***
* 设置数据源
* @param imgUrls 数据
*@param <T> 你的实体类类型
* @return GPreviewBuilder
* **/
public <T extends IThumbViewInfo> GPreviewBuilder setData(List<T> imgUrls) {
intent.putParcelableArrayListExtra("imagePaths", new ArrayList<Parcelable>(imgUrls));
return this;
}
/***
* 设置默认索引
* @param currentIndex 数据
* @return GPreviewBuilder
* **/
public GPreviewBuilder setCurrentIndex(int currentIndex) {
intent.putExtra("position", currentIndex);
return this;
}
/***
* 设置指示器类型
* @param indicatorType 枚举
* @return GPreviewBuilder
* **/
public GPreviewBuilder setType(IndicatorType indicatorType) {
intent.putExtra("type", indicatorType);
return this;
}
public void start() {
if (className == null) {
intent.setClass(mContext, GPreviewActivity.class);
} else {
intent.setClass(mContext, className);
}
mContext.startActivity(intent);
mContext.overridePendingTransition(0, 0);
intent = null;
mContext = null;
}
public GPreviewBuilder setFullscreen(boolean isFullscreen) {
intent.putExtra("isFullscreen", isFullscreen);
return this;
}
/***
* 指示器类型
* ***/
public enum IndicatorType {
Dot, Number
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.view.MotionEvent;
/**
* @author rainb
*/
public interface GestureDetector {
boolean onTouchEvent(MotionEvent ev);
boolean isScaling();
boolean isDragging();
void setOnGestureListener(OnGestureListener listener);
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.annotation.TargetApi;
import android.content.Context;
import android.widget.OverScroller;
/**
* @author rainb
*/
@TargetApi(9)
public class GingerScroller extends ScrollerProxy {
protected final OverScroller mScroller;
public GingerScroller(Context context) {
mScroller = new OverScroller(context);
}
@Override
public boolean computeScrollOffset() {
return mScroller.computeScrollOffset();
}
@Override
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
int overX, int overY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);
}
@Override
public void forceFinished(boolean finished) {
mScroller.forceFinished(finished);
}
@Override
public boolean isFinished() {
return mScroller.isFinished();
}
@Override
public int getCurrX() {
return mScroller.getCurrX();
}
@Override
public int getCurrY() {
return mScroller.getCurrY();
}
}
\ No newline at end of file
package com.yidianling.consultant.preview;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.blankj.utilcode.util.ScreenUtils;
import com.bumptech.glide.Glide;
import com.ydl.ydlcommon.base.BaseActivity;
import com.ydl.ydlcommon.bean.StatusBarOptions;
import com.yidianling.consultant.R;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author fq
*/
public class GridPreviewActivity extends BaseActivity {
private ArrayList<UserViewInfo> mThumbViewInfoList = new ArrayList<>();
MyListAdapter adapter;
private GridView gridView;
@NotNull
@Override
public StatusBarOptions getStatusViewOptions() {
return new StatusBarOptions(true, true);
}
/**
* 查找信息
* 从第一个完整可见item逆序遍历,如果初始位置为0,则不执行方法内循环
*/
private void computeBoundsBackward(int firstCompletelyVisiblePos) {
for (int i = firstCompletelyVisiblePos; i < mThumbViewInfoList.size(); i++) {
View itemView = gridView.getChildAt(i - firstCompletelyVisiblePos);
Rect bounds = new Rect();
bounds.left = ScreenUtils.getScreenWidth() / 2;
bounds.top = ScreenUtils.getScreenHeight() / 2;
bounds.right = ScreenUtils.getScreenWidth() / 2;
bounds.bottom = ScreenUtils.getScreenHeight() / 2;
// if (itemView != null) {
// ImageView thumbView = (ImageView) itemView.findViewById(R.id.iv);
// thumbView.getGlobalVisibleRect(bounds);
// }
mThumbViewInfoList.get(i).setBounds(bounds);
}
}
@Override
protected int layoutResId() {
return R.layout.consultant_picture_preview;
}
@Override
protected void initDataAndEvent() {
gridView = findViewById(R.id.grid_view);
List<String> urls = ImageUrlConfig.getUrls();
for (int i = 0; i < urls.size(); i++) {
mThumbViewInfoList.add(new UserViewInfo(urls.get(i)));
}
mThumbViewInfoList.add(4, new UserViewInfo("https://pic.ydlcdn.com/Qkkb6HmQiM.mp4", null));
adapter = new MyListAdapter();
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
computeBoundsBackward(gridView.getFirstVisiblePosition());
GPreviewBuilder.form(GridPreviewActivity.this)
.setData(mThumbViewInfoList)
.setCurrentIndex(position)
.setFullscreen(true)
.setType(GPreviewBuilder.IndicatorType.Dot)
.start();
}
});
}
private class MyListAdapter extends BaseAdapter {
@Override
public int getCount() {
return mThumbViewInfoList.size();
}
@Override
public Object getItem(int position) {
return mThumbViewInfoList.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = getLayoutInflater().inflate(R.layout.consultant_item_image, null);
ImageView iv = (ImageView) view.findViewById(R.id.iv);
Glide.with(GridPreviewActivity.this)
.load(mThumbViewInfoList.get(position).getUrl())
.into(iv);
iv.setTag(R.id.iv, mThumbViewInfoList.get(position));
return view;
}
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.view.GestureDetector;
import android.view.View;
import android.widget.ImageView;
/**
* @author rainb
*/
public interface IPhotoView {
float DEFAULT_MAX_SCALE = 3.0f;
float DEFAULT_MID_SCALE = 1.75f;
float DEFAULT_MIN_SCALE = 1.0f;
int DEFAULT_ZOOM_DURATION = 200;
/**
* Returns true if the PhotoView is set to allow zooming of Photos.
*
* @return true if the PhotoView allows zooming.
*/
boolean canZoom();
/**
* Gets the Display Rectangle of the currently displayed Drawable. The Rectangle is relative to
* this View and includes all scaling and translations.
*
* @return - RectF of Displayed Drawable
*/
RectF getDisplayRect();
/**
* Sets the Display Matrix of the currently displayed Drawable. The Rectangle is considered
* relative to this View and includes all scaling and translations.
*
* @param finalMatrix target matrix to set PhotoView to
* @return - true if rectangle was applied successfully
*/
boolean setDisplayMatrix(Matrix finalMatrix);
/**
* Copies the Display Matrix of the currently displayed Drawable. The Rectangle is considered
* relative to this View and includes all scaling and translations.
*
* @param matrix target matrix to copy to
*/
void getDisplayMatrix(Matrix matrix);
/**
* @return The current minimum scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
*/
float getMinimumScale();
/**
* @return The current medium scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
*/
float getMediumScale();
/**
* @return The current maximum scale level. What this value represents depends on the current
* {@link ImageView.ScaleType}.
*/
float getMaximumScale();
/**
* Returns the current scale value
*
* @return float - current scale value
*/
float getScale();
/**
* Return the current scale type in use by the ImageView.
*
* @return current ImageView.ScaleType
*/
ImageView.ScaleType getScaleType();
/**
* Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll
* to it's horizontal edge.
*
* @param allow whether to allow intercepting by parent element or not
*/
void setAllowParentInterceptOnEdge(boolean allow);
/**
* Sets the minimum scale level. What this value represents depends on the current {@link
* ImageView.ScaleType}.
*
* @param minimumScale minimum allowed scale
*/
void setMinimumScale(float minimumScale);
/**
* Sets the medium scale level. What this value represents depends on the current {@link ImageView.ScaleType}.
*
* @param mediumScale medium scale preset
*/
void setMediumScale(float mediumScale);
/**
* Sets the maximum scale level. What this value represents depends on the current {@link
* ImageView.ScaleType}.
*
* @param maximumScale maximum allowed scale preset
*/
void setMaximumScale(float maximumScale);
/**
* Allows to set all three scale levels at once, so you don't run into problem with setting
* medium/minimum scale before the maximum one
*
* @param minimumScale minimum allowed scale
* @param mediumScale medium allowed scale
* @param maximumScale maximum allowed scale preset
*/
void setScaleLevels(float minimumScale, float mediumScale, float maximumScale);
/**
* Register a callback to be invoked when the Photo displayed by this view is long-pressed.
*
* @param listener - Listener to be registered.
*/
void setOnLongClickListener(View.OnLongClickListener listener);
/**
* Register a callback to be invoked when the Matrix has changed for this View. An example would
* be the user panning or scaling the Photo.
*
* @param listener - Listener to be registered.
*/
void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);
/**
* Register a callback to be invoked when the Photo displayed by this View is tapped with a
* single tap.
*
* @param listener - Listener to be registered.
*/
void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
/**
* Register a callback to be invoked when the View is tapped with a single tap.
*
* @param listener - Listener to be registered.
*/
void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
/**
* Enables rotation via PhotoView internal functions.
*
* @param rotationDegree - Degree to rotate PhotoView to, should be in range 0 to 360
*/
void setRotationTo(float rotationDegree);
/**
* Enables rotation via PhotoView internal functions.
*
* @param rotationDegree - Degree to rotate PhotoView by, should be in range 0 to 360
*/
void setRotationBy(float rotationDegree);
/**
* Changes the current scale to the specified value.
*
* @param scale - Value to scale to
*/
void setScale(float scale);
/**
* Changes the current scale to the specified value.
*
* @param scale - Value to scale to
* @param animate - Whether to animate the scale
*/
void setScale(float scale, boolean animate);
/**
* Changes the current scale to the specified value, around the given focal point.
*
* @param scale - Value to scale to
* @param focalX - X Focus Point
* @param focalY - Y Focus Point
* @param animate - Whether to animate the scale
*/
void setScale(float scale, float focalX, float focalY, boolean animate);
/**
* Controls how the image should be resized or moved to match the size of the ImageView. Any
* scaling or panning will happen within the confines of this {@link
* ImageView.ScaleType}.
*
* @param scaleType - The desired scaling mode.
*/
void setScaleType(ImageView.ScaleType scaleType);
/**
* Allows you to enable/disable the zoom functionality on the ImageView. When disable the
* ImageView reverts to using the FIT_CENTER matrix.
*
* @param zoomable - Whether the zoom functionality is enabled.
*/
void setZoomable(boolean zoomable);
/**
* Extracts currently visible area to Bitmap object, if there is no image loaded yet or the
* ImageView is already destroyed, returns {@code null}
*
* @return currently visible area as bitmap or null
*/
Bitmap getVisibleRectangleBitmap();
/**
* Allows to change zoom transition speed, default value is 200 (PhotoViewAttacher.DEFAULT_ZOOM_DURATION).
* Will default to 200 if provided negative value
*
* @param milliseconds duration of zoom interpolation
*/
void setZoomTransitionDuration(int milliseconds);
/**
* Will return instance of IPhotoView (eg. PhotoViewAttacher), can be used to provide better
* integration
*
* @return IPhotoView implementation instance if available, null if not
*/
IPhotoView getIPhotoViewImplementation();
/**
* Sets custom double tap listener, to intercept default given functions. To reset behavior to
* default, you can just pass in "null" or public field of PhotoViewAttacher.defaultOnDoubleTapListener
*
* @param newOnDoubleTapListener custom OnDoubleTapListener to be set on ImageView
*/
void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener);
/**
* Will report back about scale changes
*
* @param onScaleChangeListener OnScaleChangeListener instance
*/
void setOnScaleChangeListener(PhotoViewAttacher.OnScaleChangeListener onScaleChangeListener);
/**
* Will report back about fling(single touch)
*
* @param onSingleFlingListener OnSingleFlingListener instance
*/
void setOnSingleFlingListener(PhotoViewAttacher.OnSingleFlingListener onSingleFlingListener);
}
package com.yidianling.consultant.preview;
import android.graphics.Rect;
import android.os.Parcelable;
/**
* Deprecated: 图片预览接口
*
* @author rainb
*/
public interface IThumbViewInfo extends Parcelable {
/****
* 图片地址
* @return String
* ****/
String getUrl();
/**
* 记录坐标
*
* @return Rect
***/
Rect getBounds();
/**
* 获取视频链接
***/
String getVideoUrl();
}
package com.yidianling.consultant.preview;
import android.content.Context;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
/**
* Deprecated: 加载器接口
*
* @author rainb
*/
public interface IZoomMediaLoader {
/***
* @param context 容器
* @param path 图片你的路径
* @param simpleTarget 图片加载状态回调
* ***/
void displayImage(@NonNull Fragment context, @NonNull String path, ImageView imageView, @NonNull MySimpleTarget simpleTarget);
/***
* 加载gif 图
* @param context 容器
* @param path 图片你的路径
* @param simpleTarget 图片加载状态回调
* ***/
void displayGifImage(@NonNull Fragment context, @NonNull String path, ImageView imageView, @NonNull MySimpleTarget simpleTarget);
/**
* 停止
*
* @param context 容器
**/
void onStop(@NonNull Fragment context);
/**
* 停止
*
* @param c 容器
**/
void clearMemory(@NonNull Context c);
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.annotation.TargetApi;
import android.content.Context;
/**
* @author rainb
*/
@TargetApi(14)
public class IcsScroller extends GingerScroller {
public IcsScroller(Context context) {
super(context);
}
@Override
public boolean computeScrollOffset() {
return mScroller.computeScrollOffset();
}
}
package com.yidianling.consultant.preview;
import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
/**
* Deprecated: 图片加载回调状态接口
*
* @author rainb
*/
public interface MySimpleTarget {
/**
* Callback when an image has been successfully loaded.
* <p>
* <strong>Note:</strong> You must not recycle the bitmap.
*/
void onResourceReady();
/**
* Callback indicating the image could not be successfully loaded.
*
* @param errorRes 内容
*/
void onLoadFailed(@Nullable Drawable errorRes);
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
/**
* @author rainb
*/
public interface OnGestureListener {
void onDrag(float dx, float dy);
void onFling(float startX, float startY, float velocityX,
float velocityY);
void onScale(float scaleFactor, float focusX, float focusY);
}
\ No newline at end of file
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.GestureDetector;
public class PhotoView extends androidx.appcompat.widget.AppCompatImageView implements IPhotoView {
private PhotoViewAttacher mAttacher;
private ScaleType mPendingScaleType;
public PhotoView(Context context) {
this(context, null);
}
public PhotoView(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public PhotoView(Context context, AttributeSet attr, int defStyle) {
super(context, attr, defStyle);
super.setScaleType(ScaleType.MATRIX);
init();
}
protected void init() {
if (null == mAttacher || null == mAttacher.getImageView()) {
mAttacher = new PhotoViewAttacher(this);
}
if (null != mPendingScaleType) {
setScaleType(mPendingScaleType);
mPendingScaleType = null;
}
}
@Override
public void setRotationTo(float rotationDegree) {
mAttacher.setRotationTo(rotationDegree);
}
@Override
public void setRotationBy(float rotationDegree) {
mAttacher.setRotationBy(rotationDegree);
}
@Override
public boolean canZoom() {
return mAttacher.canZoom();
}
@Override
public RectF getDisplayRect() {
return mAttacher.getDisplayRect();
}
@Override
public void getDisplayMatrix(Matrix matrix) {
mAttacher.getDisplayMatrix(matrix);
}
@Override
public boolean setDisplayMatrix(Matrix finalRectangle) {
return mAttacher.setDisplayMatrix(finalRectangle);
}
@Override
public float getMinimumScale() {
return mAttacher.getMinimumScale();
}
@Override
public float getMediumScale() {
return mAttacher.getMediumScale();
}
@Override
public float getMaximumScale() {
return mAttacher.getMaximumScale();
}
@Override
public float getScale() {
return mAttacher.getScale();
}
@Override
public ScaleType getScaleType() {
return mAttacher.getScaleType();
}
@Override
public Matrix getImageMatrix() {
return mAttacher.getImageMatrix();
}
@Override
public void setAllowParentInterceptOnEdge(boolean allow) {
mAttacher.setAllowParentInterceptOnEdge(allow);
}
@Override
public void setMinimumScale(float minimumScale) {
mAttacher.setMinimumScale(minimumScale);
}
@Override
public void setMediumScale(float mediumScale) {
mAttacher.setMediumScale(mediumScale);
}
@Override
public void setMaximumScale(float maximumScale) {
mAttacher.setMaximumScale(maximumScale);
}
@Override
public void setScaleLevels(float minimumScale, float mediumScale, float maximumScale) {
mAttacher.setScaleLevels(minimumScale, mediumScale, maximumScale);
}
@Override
// setImageBitmap calls through to this method
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
if (null != mAttacher) {
mAttacher.update();
}
}
@Override
protected boolean setFrame(int l, int t, int r, int b) {
boolean changed = super.setFrame(l, t, r, b);
if (null != mAttacher) {
mAttacher.update();
}
return changed;
}
@Override
public void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener) {
mAttacher.setOnMatrixChangeListener(listener);
}
@Override
public void setOnLongClickListener(OnLongClickListener l) {
mAttacher.setOnLongClickListener(l);
}
@Override
public void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener) {
mAttacher.setOnPhotoTapListener(listener);
}
@Override
public void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener) {
mAttacher.setOnViewTapListener(listener);
}
@Override
public void setScale(float scale) {
mAttacher.setScale(scale);
}
@Override
public void setScale(float scale, boolean animate) {
mAttacher.setScale(scale, animate);
}
@Override
public void setScale(float scale, float focalX, float focalY, boolean animate) {
mAttacher.setScale(scale, focalX, focalY, animate);
}
@Override
public void setScaleType(ScaleType scaleType) {
if (null != mAttacher) {
mAttacher.setScaleType(scaleType);
} else {
mPendingScaleType = scaleType;
}
}
@Override
public void setZoomable(boolean zoomable) {
mAttacher.setZoomable(zoomable);
}
@Override
public Bitmap getVisibleRectangleBitmap() {
return mAttacher.getVisibleRectangleBitmap();
}
@Override
public void setZoomTransitionDuration(int milliseconds) {
mAttacher.setZoomTransitionDuration(milliseconds);
}
@Override
public IPhotoView getIPhotoViewImplementation() {
return mAttacher;
}
@Override
public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener newOnDoubleTapListener) {
mAttacher.setOnDoubleTapListener(newOnDoubleTapListener);
}
@Override
public void setOnScaleChangeListener(PhotoViewAttacher.OnScaleChangeListener onScaleChangeListener) {
mAttacher.setOnScaleChangeListener(onScaleChangeListener);
}
@Override
public void setOnSingleFlingListener(PhotoViewAttacher.OnSingleFlingListener onSingleFlingListener) {
mAttacher.setOnSingleFlingListener(onSingleFlingListener);
}
@Override
protected void onDetachedFromWindow() {
mAttacher.cleanup();
mAttacher.resetMatrix();
mAttacher = null;
super.onDetachedFromWindow();
}
@Override
protected void onAttachedToWindow() {
init();
super.onAttachedToWindow();
}
public void resetMatrix() {
if (mAttacher != null) {
mAttacher.cleanup();
mAttacher.resetMatrix();
}
}
}
package com.yidianling.consultant.preview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.viewpager.widget.ViewPager;
/**
* Issues With ViewGroups
*
* @author rainb
*/
public class PhotoViewPager extends ViewPager {
public PhotoViewPager(Context context) {
super(context);
}
public PhotoViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
}
}
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.content.Context;
import android.widget.Scroller;
/**
* @author rainb
*/
public class PreGingerScroller extends ScrollerProxy {
private final Scroller mScroller;
public PreGingerScroller(Context context) {
mScroller = new Scroller(context);
}
@Override
public boolean computeScrollOffset() {
return mScroller.computeScrollOffset();
}
@Override
public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
int overX, int overY) {
mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
}
@Override
public void forceFinished(boolean finished) {
mScroller.forceFinished(finished);
}
@Override
public boolean isFinished() {
return mScroller.isFinished();
}
@Override
public int getCurrX() {
return mScroller.getCurrX();
}
@Override
public int getCurrY() {
return mScroller.getCurrY();
}
}
\ No newline at end of file
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.yidianling.consultant.preview;
import android.content.Context;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
/**
* @author rainb
*/
public abstract class ScrollerProxy {
public static ScrollerProxy getScroller(Context context) {
if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {
return new PreGingerScroller(context);
} else if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) {
return new GingerScroller(context);
} else {
return new IcsScroller(context);
}
}
public abstract boolean computeScrollOffset();
public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,
int maxY, int overX, int overY);
public abstract void forceFinished(boolean finished);
public abstract boolean isFinished();
public abstract int getCurrX();
public abstract int getCurrY();
}
package com.yidianling.consultant.preview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import org.jetbrains.annotations.NotNull;
/**
* @author rainb
*/
public class TestImageLoader implements IZoomMediaLoader {
@Override
public void displayImage(@NonNull Fragment context, @NonNull String path, final ImageView imageView, @NonNull final MySimpleTarget simpleTarget) {
Glide.with(context).asBitmap().load(path)
// .placeholder(android.R.color.darker_gray)
.fitCenter()
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull @NotNull Bitmap resource, @Nullable @org.jetbrains.annotations.Nullable Transition<? super Bitmap> transition) {
simpleTarget.onResourceReady();
imageView.setImageBitmap(resource);
}
});
}
@Override
public void displayGifImage(@NonNull Fragment context, @NonNull String path, ImageView imageView, @NonNull final MySimpleTarget simpleTarget) {
}
@Override
public void onStop(@NonNull Fragment context) {
Glide.with(context).onStop();
}
@Override
public void clearMemory(@NonNull Context c) {
Glide.get(c).clearMemory();
}
}
package com.yidianling.consultant.preview;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Deprecated: 图片预览实体类
*
* @author rainb
*/
public class UserViewInfo implements IThumbViewInfo {
private String url; //图片地址
private Rect mBounds; // 记录坐标
private String user = "用户字段";
private String videoUrl;
public UserViewInfo(String url) {
this.url = url;
}
public UserViewInfo(String videoUrl, String url) {
this.url = url;
this.videoUrl = videoUrl;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
@Override
public String getUrl() {//将你的图片地址字段返回
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public Rect getBounds() {//将你的图片显示坐标字段返回
return mBounds;
}
@Override
public String getVideoUrl() {
return videoUrl;
}
public void setBounds(Rect bounds) {
mBounds = bounds;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.url);
dest.writeParcelable(this.mBounds, flags);
dest.writeString(this.user);
dest.writeString(this.videoUrl);
}
protected UserViewInfo(Parcel in) {
this.url = in.readString();
this.mBounds = in.readParcelable(Rect.class.getClassLoader());
this.user = in.readString();
this.videoUrl = in.readString();
}
public static final Parcelable.Creator<UserViewInfo> CREATOR = new Parcelable.Creator<UserViewInfo>() {
@Override
public UserViewInfo createFromParcel(Parcel source) {
return new UserViewInfo(source);
}
@Override
public UserViewInfo[] newArray(int size) {
return new UserViewInfo[size];
}
};
}
package com.yidianling.consultant.preview;
/*******************************************************************************
* Copyright 2011, 2012 Chris Banes.
*
* 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.
*******************************************************************************/
import android.content.Context;
import android.os.Build;
/**
* @author rainb
*/
public final class VersionedGestureDetector {
public static GestureDetector newInstance(Context context,
OnGestureListener listener) {
final int sdkVersion = Build.VERSION.SDK_INT;
GestureDetector detector;
if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
detector = new CupcakeGestureDetector(context);
} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
detector = new EclairGestureDetector(context);
} else {
detector = new FroyoGestureDetector(context);
}
detector.setOnGestureListener(listener);
return detector;
}
}
\ No newline at end of file
package com.yidianling.consultant.preview;
/**
* Deprecated: 图片加载管理器
*
* @author rainb
*/
public class ZoomMediaLoader {
private volatile IZoomMediaLoader loader;
public static ZoomMediaLoader getInstance() {
return Holder.holder;
}
private ZoomMediaLoader() {
}
private static class Holder {
static ZoomMediaLoader holder = new ZoomMediaLoader();
}
/****
* 初始化加载图片类
* @param loader 自定义
* **/
public void init(IZoomMediaLoader loader) {
this.loader = loader;
}
public IZoomMediaLoader getLoader() {
if (loader == null) {
throw new NullPointerException("ZoomMediaLoader loader no init");
}
return loader;
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.yidianling.consultant.preview.PhotoViewPager
android:background="@android:color/transparent"
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:clickable="false"
android:contentDescription="@null"
android:focusable="false"
android:scaleType="centerCrop"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<GridView
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="2"
android:layout_marginLeft="@dimen/platform_dp_10"
android:layout_marginRight="@dimen/platform_dp_10"
android:horizontalSpacing="@dimen/platform_dp_10"
android:verticalSpacing="@dimen/platform_dp_10"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
tools:ignore="ResourceName">
<com.yidianling.consultant.preview.SmoothImageView
android:id="@+id/photoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:scaleType="centerInside" />
<RelativeLayout
android:id="@+id/videoContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.dou361.ijkplayer.widget.IjkVideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/btnLL"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="@dimen/platform_dp_40">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/platform_dp_20"
android:layout_marginRight="@dimen/platform_dp_20"
android:layout_weight="1"
android:background="@drawable/bg_btn_dis" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/platform_dp_20"
android:layout_marginRight="@dimen/platform_dp_20"
android:layout_weight="1"
android:background="@color/green_btn" />
</LinearLayout>
<ProgressBar
android:id="@+id/loading"
style="@android:style/Widget.DeviceDefault.Light.ProgressBar"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:visibility="visible" />
<ImageView
android:id="@+id/btnVideo"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerInParent="true"
android:alpha="0"
android:visibility="gone" />
</RelativeLayout>
\ No newline at end of file
......@@ -8,4 +8,7 @@
<string name="consultant_reload_hint">加载失败,换个网络环境试试吧</string>
<item name="consultant_item_image_key" type="id" />
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment