Skip to content

Commit

Permalink
Add image viewer for topic details
Browse files Browse the repository at this point in the history
close #2
  • Loading branch information
mzlogin committed Nov 18, 2017
1 parent c6ee49e commit fb6cb5c
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,5 @@ dependencies {
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
compile 'com.github.medyo:android-about-page:1.2.1'
compile 'com.vdurmont:emoji-java:4.0.0'
compile 'com.bm.photoview:library:1.4.1'
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.mazhuang.guanggoo.nodescloud.NodesCloudPresenter;
import org.mazhuang.guanggoo.topicdetail.TopicDetailFragment;
import org.mazhuang.guanggoo.topicdetail.TopicDetailPresenter;
import org.mazhuang.guanggoo.topicdetail.viewimage.ViewImageFragment;
import org.mazhuang.guanggoo.topicdetail.viewimage.ViewImagePresenter;
import org.mazhuang.guanggoo.topiclist.TopicListFragment;
import org.mazhuang.guanggoo.topiclist.TopicListPresenter;
import org.mazhuang.guanggoo.userprofile.UserProfileFragment;
Expand All @@ -21,6 +23,7 @@
import org.mazhuang.guanggoo.util.ConstantUtil;
import org.mazhuang.guanggoo.util.UrlUtil;

import java.util.PriorityQueue;
import java.util.regex.Pattern;

/**
Expand All @@ -43,6 +46,7 @@ public enum PageType {
USER_REPLIES, // 个人回复列表
ABOUT, // 关于
NEW_TOPIC, // 发表新主题
VIEW_IMAGE, // 查看图片
}

public static final Pattern HOME_TOPIC_LIST_PATTERN = Pattern.compile("^http://www.guanggoo.com[/]?$");
Expand All @@ -56,6 +60,7 @@ public enum PageType {
public static final Pattern USER_TOPICS_PATTERN = Pattern.compile("^http://www.guanggoo.com/u/\\w+/topics$");
public static final Pattern USER_REPLIES_PATTERN = Pattern.compile("^http://www.guanggoo.com/u/\\w+/replies$");
public static final Pattern NEW_TOPIC_PATTERN = Pattern.compile("^http://www.guanggoo.com/t/create/\\w+$");
public static final Pattern VIEW_IMAGE_PATTERN = Pattern.compile("^http[s]?://.+\\.(png|jpg|jpeg)$");


public static BaseFragment getFragmentByUrl(String url) {
Expand Down Expand Up @@ -148,6 +153,11 @@ public static BaseFragment getFragmentByPageType(PageType type) {
}
break;

case VIEW_IMAGE:
fragment = new ViewImageFragment();
new ViewImagePresenter((ViewImageFragment) fragment);
break;

case ABOUT:
fragment = new AboutFragment();
break;
Expand Down Expand Up @@ -209,6 +219,10 @@ public static PageType getPageTypeByUrl(String url) {
return PageType.NEW_TOPIC;
}

if (VIEW_IMAGE_PATTERN.matcher(url).find()) {
return PageType.VIEW_IMAGE;
}

if (ConstantUtil.ABOUT_URL.equals(url)) {
return PageType.ABOUT;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.mazhuang.guanggoo.data.entity.Favorite;
import org.mazhuang.guanggoo.data.entity.Node;
import org.mazhuang.guanggoo.data.entity.TopicDetail;
import org.mazhuang.guanggoo.router.FragmentFactory;
import org.mazhuang.guanggoo.util.ConstantUtil;

import butterknife.BindView;
Expand Down Expand Up @@ -291,6 +292,12 @@ private void initWebView() {
mContentWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
FragmentFactory.PageType pageType = FragmentFactory.getPageTypeByUrl(url);
if (mListener != null && pageType == FragmentFactory.PageType.VIEW_IMAGE) {
mListener.openPage(url, getString(R.string.view_image));
return true;
}

startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.mazhuang.guanggoo.topicdetail.viewimage;

import com.bm.library.PhotoView;

import org.mazhuang.guanggoo.base.BasePresenter;
import org.mazhuang.guanggoo.base.BaseView;

/**
* Created by mazhuang on 2017/11/18.
*/

public interface ViewImageContract {
interface Presenter extends BasePresenter {
void saveImage(PhotoView photoViewTemp);
}

interface View extends BaseView<Presenter> {
void onSaveImageSucceed();
void onSaveImageFailed(String msg);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package org.mazhuang.guanggoo.topicdetail.viewimage;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.bm.library.PhotoView;
import com.bumptech.glide.Glide;

import org.mazhuang.guanggoo.R;
import org.mazhuang.guanggoo.base.BaseFragment;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
* Created by mazhuang on 2017/11/18.
*/

public class ViewImageFragment extends BaseFragment<ViewImageContract.Presenter> implements ViewImageContract.View {

@BindView(R.id.image) PhotoView mImageView;

private static final int PERMISSIONS_REQUEST_CODE = 100;

private static final String[] sPermissions = {
Manifest.permission.WRITE_EXTERNAL_STORAGE
};

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

initParams();

setHasOptionsMenu(true);
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_view_image, container, false);

ButterKnife.bind(this, root);

initPhotoView();

loadImage();

return root;
}

private void initPhotoView() {
mImageView.enable();
}

private void loadImage() {
Glide.with(this)
.load(mUrl)
.into(mImageView);
}

@Override
public String getTitle() {
if (TextUtils.isEmpty(mTitle)) {
return getString(R.string.view_image);
} else {
return mTitle;
}
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.view_image, menu);
super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save:
boolean isAllPermissionsGranted = true;
for (String permission : sPermissions) {
if (ActivityCompat.checkSelfPermission(getContext().getApplicationContext(), permission) != PackageManager.PERMISSION_GRANTED) {
isAllPermissionsGranted = false;
break;
}
}

if (!isAllPermissionsGranted) {
requestPermissions(sPermissions, PERMISSIONS_REQUEST_CODE);
} else {
mPresenter.saveImage(mImageView);
}

return true;

default:
break;
}

return super.onOptionsItemSelected(item);
}

@Override
public void onSaveImageSucceed() {
if (getContext() == null) {
return;
}

toast("保存成功");
}

@Override
public void onSaveImageFailed(String msg) {
if (getContext() == null) {
return;
}

toast(msg);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_CODE) {
boolean isAllPermissionsGranted = true;
if (grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
isAllPermissionsGranted = false;
break;
}
}
} else {
isAllPermissionsGranted = false;
}

if (isAllPermissionsGranted) {
mPresenter.saveImage(mImageView);
return;
}

toast("保存图片需要开启读写文件权限,请检查权限设置");

} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.mazhuang.guanggoo.topicdetail.viewimage;

import android.graphics.Bitmap;

import com.bm.library.PhotoView;
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;

import org.mazhuang.guanggoo.util.FileUtils;

/**
* Created by mazhuang on 2017/11/18.
*/

public class ViewImagePresenter implements ViewImageContract.Presenter {

private ViewImageContract.View mView;

public ViewImagePresenter(ViewImageContract.View view) {
mView = view;
mView.setPresenter(this);
}

@Override
public void saveImage(final PhotoView photoViewTemp) {
if (photoViewTemp != null) {
GlideBitmapDrawable glideBitmapDrawable = (GlideBitmapDrawable) photoViewTemp.getDrawable();
if (glideBitmapDrawable == null) {
return;
}
Bitmap bitmap = glideBitmapDrawable.getBitmap();
if (bitmap == null) {
return;
}
mView.startLoading();
FileUtils.saveImage(photoViewTemp.getContext(), bitmap, new FileUtils.SaveResultCallback() {
@Override
public void onSavedSuccess() {
photoViewTemp.post(new Runnable() {
@Override
public void run() {
mView.stopLoading();
mView.onSaveImageSucceed();
}
});
}

@Override
public void onSavedFailed() {
photoViewTemp.post(new Runnable() {
@Override
public void run() {
mView.stopLoading();
mView.onSaveImageFailed("保存失败");
}
});
}
});
}
}
}
58 changes: 58 additions & 0 deletions app/src/main/java/org/mazhuang/guanggoo/util/FileUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.mazhuang.guanggoo.util;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Created by mazhuang on 2017/11/18.
* code from https://www.ctolib.com/topics-110262.html
*/

public class FileUtils {
public static void saveImage(final Context context, final Bitmap bmp , final SaveResultCallback saveResultCallback) {
new Thread(new Runnable() {
@Override
public void run() {
File appDir = new File(Environment.getExternalStorageDirectory(), "out_photo");
if (!appDir.exists()) {
appDir.mkdir();
}
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");//设置以当前时间格式为图片名称
String fileName = df.format(new Date()) + ".png";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
saveResultCallback.onSavedSuccess();
} catch (FileNotFoundException e) {
saveResultCallback.onSavedFailed();
e.printStackTrace();
} catch (IOException e) {
saveResultCallback.onSavedFailed();
e.printStackTrace();
}

//保存图片后发送广播通知更新数据库
Uri uri = Uri.fromFile(file);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
}
}).start();
}

public interface SaveResultCallback{
void onSavedSuccess();
void onSavedFailed();
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_menu_save.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>
Loading

0 comments on commit fb6cb5c

Please sign in to comment.