├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── peng3 │ │ └── big │ │ └── big │ │ └── activity │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ ├── activity │ │ │ ├── MainActivity.java │ │ │ └── ShowImageFromWebActivity.java │ │ ├── adapter │ │ │ └── ImageBrowserAdapter.java │ │ ├── api │ │ │ ├── ApiManager.java │ │ │ ├── ApiService.java │ │ │ ├── OKHttpFactory.java │ │ │ └── RetrofitFactory.java │ │ ├── utils │ │ │ ├── BitmapUtil.java │ │ │ ├── Constant.java │ │ │ ├── ImageLoaderUtils.java │ │ │ ├── SystemApplication.java │ │ │ └── ToastManager.java │ │ └── view │ │ │ ├── ActionSheetDialog.java │ │ │ ├── PhotoViewViewPager.java │ │ │ └── ShowImageWebView.java │ └── res │ │ ├── anim │ │ ├── actionsheet_dialog_in.xml │ │ └── actionsheet_dialog_out.xml │ │ ├── drawable-xhdpi │ │ ├── avatar_default.png │ │ ├── image_default_rect.png │ │ ├── toast_actionsheet_bottom_normal.9.png │ │ ├── toast_actionsheet_bottom_pressed.9.png │ │ ├── toast_actionsheet_middle_normal.9.png │ │ ├── toast_actionsheet_middle_pressed.9.png │ │ ├── toast_actionsheet_single_normal.9.png │ │ ├── toast_actionsheet_single_pressed.9.png │ │ ├── toast_actionsheet_top_normal.9.png │ │ └── toast_actionsheet_top_pressed.9.png │ │ ├── drawable │ │ ├── actionsheet_bottom_selector.xml │ │ ├── actionsheet_middle_selector.xml │ │ ├── actionsheet_single_selector.xml │ │ ├── actionsheet_top_selector.xml │ │ └── shape_corner_rect_gray.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_show_image_from_web.xml │ │ ├── item_image_browser.xml │ │ └── toast_view_actionsheet.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── peng3 │ └── big │ └── big │ └── activity │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── shotsnap └── ShowZoomableImageFromWebView.gif /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | ShowImageFromWebView -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This is a simple demo for showing an image from the webView and downloading an 2 | # image from the webView. 3 | 4 | # The ShowImageWebView is a wrapping widget for the webView to show an image from the webView 5 | # and download an image from the webView. 6 | 7 | 1. 点击 WebView 页面的图片实现开启查看图片模式,即可以显示点击的图片,然后滑动显示下一张图片。 8 | 9 | ![showImage](https://github.com/yongyu0102/WeeklyBlogImages/blob/master/phase5/showImage.gif) 10 | 11 | 2. 长按 WebView 页面图片弹出对话框可以选择保存长按的图片到本地相册。 12 | 13 | ![showpop](https://github.com/yongyu0102/WeeklyBlogImages/blob/master/phase5/showpop.gif) 14 | 15 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.peng.zhang.showzoomableimagefromwebview" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:24.2.0' 26 | compile 'com.squareup.okhttp3:okhttp:3.2.0' 27 | compile 'com.squareup.okio:okio:1.6.0' 28 | //photoView 29 | compile 'com.github.chrisbanes:PhotoView:1.3.0' 30 | compile 'com.github.bumptech.glide:glide:3.7.0' 31 | /*网络请求 rotrofit+okhttp*/ 32 | compile 'com.squareup.retrofit2:retrofit:2.1.0' 33 | compile 'com.squareup.retrofit2:converter-gson:2.1.0' 34 | compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' 35 | compile 'com.squareup.okhttp3:logging-interceptor:3.3.0' 36 | /*json解析 gson*/ 37 | compile 'com.google.code.gson:gson:2.7' 38 | /*rx-android-java*/ 39 | compile 'io.reactivex:rxjava:1.1.9' 40 | compile 'io.reactivex:rxandroid:1.2.1' 41 | compile 'com.trello:rxlifecycle:0.7.0' 42 | compile 'com.trello:rxlifecycle-components:0.7.0' 43 | } 44 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/zp/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/peng3/big/big/activity/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.peng3.big.big.activity; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.os.Environment; 8 | import android.os.Handler; 9 | import android.view.View; 10 | import android.webkit.WebView; 11 | import android.webkit.WebViewClient; 12 | import android.widget.Toast; 13 | 14 | import com.peng.zhang.activity.R; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | import utils.ImageLoaderUtils; 22 | import view.ActionSheetDialog; 23 | import view.ShowImageWebView; 24 | 25 | /** 26 | * description: 加载 WebView 主界面 27 | * author:pz 28 | * 时间:2016/10/18 :23:11 29 | */ 30 | public class MainActivity extends Activity { 31 | 32 | private ShowImageWebView mWebView; 33 | private String url = "http://news.sina.com.cn/china/xlxw/2016-10-23/doc-ifxwztru6946123.shtml"; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_main); 39 | mWebView = (ShowImageWebView) findViewById(R.id.web_view); 40 | 41 | mWebView.getSettings().setJavaScriptEnabled(true); 42 | mWebView.getSettings().setDefaultTextEncodingName("UTF -8"); 43 | mWebView.setWebViewClient(new WebViewClient() { 44 | // 网页跳转 45 | @Override 46 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 47 | view.loadUrl(url); 48 | return true; 49 | } 50 | 51 | // 网页加载结束 52 | @Override 53 | public void onPageFinished(WebView view, String url) { 54 | super.onPageFinished(view, url); 55 | // web 页面加载完成,添加监听图片的点击 js 函数 56 | mWebView.setImageClickListner(); 57 | //解析 HTML 58 | mWebView.parseHTML(view); 59 | } 60 | 61 | @Override 62 | public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { 63 | Toast.makeText(MainActivity.this, "请检查您的网络设置", Toast.LENGTH_SHORT).show(); 64 | } 65 | }); 66 | 67 | mWebView.loadUrl(url); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/activity/ShowImageFromWebActivity.java: -------------------------------------------------------------------------------- 1 | package activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Environment; 6 | import android.os.Handler; 7 | import android.support.v4.view.ViewPager; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.TextView; 11 | import android.widget.Toast; 12 | 13 | import com.peng.zhang.activity.R; 14 | 15 | import java.util.ArrayList; 16 | 17 | import adapter.ImageBrowserAdapter; 18 | import utils.Constant; 19 | import utils.ImageLoaderUtils; 20 | 21 | public class ShowImageFromWebActivity extends Activity implements View.OnClickListener { 22 | private ViewPager vpImageBrowser; 23 | private TextView tvImageIndex; 24 | private Button btnSave; 25 | 26 | private ImageBrowserAdapter adapter; 27 | private ArrayList imgUrls; 28 | private String url; 29 | private int currentIndex; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_show_image_from_web); 35 | initView(); 36 | initListener(); 37 | initData(); 38 | } 39 | 40 | private void initView() { 41 | vpImageBrowser = (ViewPager) findViewById(R.id.vp_image_browser); 42 | tvImageIndex = (TextView) findViewById(R.id.tv_image_index); 43 | btnSave = (Button) findViewById(R.id.btn_save); 44 | } 45 | 46 | private void initData() { 47 | imgUrls = getIntent().getStringArrayListExtra(Constant.IMAGE_URL_ALL); 48 | url = getIntent().getStringExtra(Constant.IMAGE_URL); 49 | int position = imgUrls.indexOf(url); 50 | adapter = new ImageBrowserAdapter(this, imgUrls); 51 | vpImageBrowser.setAdapter(adapter); 52 | final int size = imgUrls.size(); 53 | 54 | if (size > 1) { 55 | tvImageIndex.setVisibility(View.VISIBLE); 56 | tvImageIndex.setText((position + 1) + "/" + size); 57 | } else { 58 | tvImageIndex.setVisibility(View.GONE); 59 | } 60 | 61 | vpImageBrowser.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { 62 | 63 | @Override 64 | public void onPageSelected(int arg0) { 65 | currentIndex = arg0; 66 | int index = arg0 % size; 67 | tvImageIndex.setText((index + 1) + "/" + size); 68 | 69 | } 70 | 71 | @Override 72 | public void onPageScrolled(int arg0, float arg1, int arg2) { 73 | // TODO Auto-generated method stub 74 | 75 | } 76 | 77 | @Override 78 | public void onPageScrollStateChanged(int arg0) { 79 | // TODO Auto-generated method stub 80 | 81 | } 82 | }); 83 | 84 | vpImageBrowser.setCurrentItem(position); 85 | } 86 | 87 | private void initListener() { 88 | btnSave.setOnClickListener(this); 89 | } 90 | 91 | @Override 92 | public void onClick(View v) { 93 | switch (v.getId()) { 94 | case R.id.btn_save: 95 | downloadImage(); 96 | break; 97 | } 98 | } 99 | 100 | /** 101 | * 开始下载图片 102 | */ 103 | private void downloadImage() { 104 | ImageLoaderUtils.downLoadImage(imgUrls.get(currentIndex), Environment.getExternalStorageDirectory().getAbsolutePath() + "/ImagesFromWebView", this); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/adapter/ImageBrowserAdapter.java: -------------------------------------------------------------------------------- 1 | package adapter; 2 | 3 | import android.app.Activity; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.load.resource.drawable.GlideDrawable; 11 | import com.bumptech.glide.request.animation.GlideAnimation; 12 | import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; 13 | import com.peng.zhang.activity.R; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | import uk.co.senab.photoview.PhotoViewAttacher; 19 | import utils.ImageLoaderUtils; 20 | 21 | public class ImageBrowserAdapter extends PagerAdapter { 22 | 23 | private Activity context; 24 | private List picUrls; 25 | 26 | public ImageBrowserAdapter(Activity context, ArrayList picUrls) { 27 | this.context = context; 28 | this.picUrls = picUrls; 29 | } 30 | 31 | 32 | @Override 33 | public int getCount() { 34 | 35 | return picUrls.size(); 36 | } 37 | 38 | @Override 39 | public boolean isViewFromObject(View view, Object object) { 40 | return view == object; 41 | } 42 | 43 | @Override 44 | public View instantiateItem(ViewGroup container, int position) { 45 | View view = View.inflate(context, R.layout.item_image_browser, null); 46 | ImageView pvShowImage = (ImageView) view.findViewById(R.id.pv_show_image); 47 | String picUrl = picUrls.get(position); 48 | final PhotoViewAttacher photoViewAttacher=new PhotoViewAttacher(pvShowImage); 49 | photoViewAttacher.setScaleType(ImageView.ScaleType.FIT_CENTER); 50 | photoViewAttacher.setMinimumScale(1F); 51 | ImageLoaderUtils.displayScaleImage(context,pvShowImage,picUrl,photoViewAttacher); 52 | container.addView(view); 53 | return view; 54 | } 55 | 56 | @Override 57 | public void destroyItem(ViewGroup container, int position, Object object) { 58 | container.removeView((View) object); 59 | } 60 | 61 | 62 | 63 | 64 | } -------------------------------------------------------------------------------- /app/src/main/java/api/ApiManager.java: -------------------------------------------------------------------------------- 1 | package api; 2 | 3 | /** 4 | * Description: 5 | * Author:pz 6 | * Date:2016/10/24:14:54 7 | */ 8 | public class ApiManager { 9 | private static ApiManager apiManager = null; 10 | private ApiService mApiService; 11 | 12 | private ApiManager() { 13 | mApiService = RetrofitFactory.getInstance().getRetrofit().create(ApiService.class); 14 | } 15 | 16 | /** 17 | * 得到apiManage实例 18 | * 19 | * @return 得到apiManage实例 20 | */ 21 | public static ApiManager getInstance() { 22 | if (apiManager == null) { 23 | synchronized (ApiManager.class) { 24 | if (apiManager == null) { 25 | apiManager = new ApiManager(); 26 | } 27 | } 28 | } 29 | return apiManager; 30 | } 31 | 32 | /** 33 | * 得到ApiService实例 34 | * 35 | * @return ApiService 36 | */ 37 | public ApiService getApiService() { 38 | return mApiService; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/api/ApiService.java: -------------------------------------------------------------------------------- 1 | package api; 2 | 3 | import okhttp3.ResponseBody; 4 | import retrofit2.http.GET; 5 | import retrofit2.http.Url; 6 | import rx.Observable; 7 | 8 | /** 9 | * Description: 10 | * Author:pz 11 | * Date:2016/10/24:14:45 12 | */ 13 | public interface ApiService { 14 | 15 | @GET 16 | Observable downLoadImage(@Url String url); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/api/OKHttpFactory.java: -------------------------------------------------------------------------------- 1 | package api; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import okhttp3.OkHttpClient; 6 | import okhttp3.logging.HttpLoggingInterceptor; 7 | 8 | /** 9 | * description:OkHttpClient 10 | * author:pz 11 | * data:2016/10/24 12 | */ 13 | public class OKHttpFactory { 14 | private static final int TIMEOUT_READ = 50; 15 | private static final int TIMEOUT_CONNECTION = 50; 16 | 17 | private static OKHttpFactory okHttpFactory = null; 18 | private OkHttpClient okHttpClient = null; 19 | 20 | private OKHttpFactory() { 21 | HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); 22 | httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 23 | okHttpClient = new OkHttpClient.Builder() 24 | .addInterceptor(httpLoggingInterceptor) 25 | //失败重连 26 | .retryOnConnectionFailure(true) 27 | //time out 28 | .readTimeout(TIMEOUT_READ, TimeUnit.SECONDS) 29 | .connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS) 30 | .build(); 31 | } 32 | 33 | /** 34 | * 得到okHttpFactory实例 35 | * 36 | * @return okHttpFactory 37 | */ 38 | public static OKHttpFactory getInstance() { 39 | if (okHttpFactory == null) { 40 | synchronized (OKHttpFactory.class) { 41 | if (okHttpFactory == null) { 42 | okHttpFactory = new OKHttpFactory(); 43 | } 44 | } 45 | } 46 | return okHttpFactory; 47 | } 48 | 49 | /** 50 | * 得到okhttpClient实例 51 | * 52 | * @return okhttpClient 53 | */ 54 | public OkHttpClient getOkHttpClient() { 55 | return okHttpClient; 56 | } 57 | 58 | 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/api/RetrofitFactory.java: -------------------------------------------------------------------------------- 1 | package api; 2 | 3 | import retrofit2.Retrofit; 4 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 5 | import retrofit2.converter.gson.GsonConverterFactory; 6 | import utils.Constant; 7 | 8 | /** 9 | * description: Retrofit 10 | * author:pz 11 | * data:2016/10/24 12 | */ 13 | public class RetrofitFactory { 14 | private static RetrofitFactory retrofitFactory = null; 15 | private Retrofit retrofit = null; 16 | 17 | private RetrofitFactory() { 18 | retrofit = new Retrofit.Builder() 19 | //设置OKHttpClient 20 | .client(OKHttpFactory.getInstance().getOkHttpClient()) 21 | //gson转化器 22 | .addConverterFactory(GsonConverterFactory.create()) 23 | //rx转换器 24 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 25 | //baseUrl 26 | .baseUrl(Constant.BASE_URL) 27 | .build(); 28 | } 29 | 30 | /** 31 | * 得到retorfitFactory实例 32 | * 33 | * @return retorfitFactory 34 | */ 35 | public static RetrofitFactory getInstance() { 36 | if (retrofitFactory == null) { 37 | synchronized (RetrofitFactory.class) { 38 | if (retrofitFactory == null) { 39 | retrofitFactory = new RetrofitFactory(); 40 | } 41 | } 42 | } 43 | return retrofitFactory; 44 | } 45 | 46 | /** 47 | * 得到retorfit实例 48 | * 49 | * @return retorfit 50 | */ 51 | public Retrofit getRetrofit() { 52 | return retrofit; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/utils/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Bitmap; 6 | import android.net.Uri; 7 | import android.os.Environment; 8 | 9 | import java.io.File; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | 14 | /** 15 | * description: BitmapUtil 16 | * author:pz 17 | * data:2016/10/24 18 | */ 19 | public class BitmapUtil { 20 | 21 | /** 22 | * description:将 bitmap 保存到相册 23 | * author:pz 24 | * data:2016/10/20 25 | */ 26 | public static void saveImageToGallery(Context context, Bitmap bmp) { 27 | // 首先保存图片 28 | File appDir = new File(Environment.getExternalStorageDirectory(), "cab/pics"); 29 | if (!appDir.exists()) { 30 | appDir.mkdir(); 31 | } 32 | String fileName = System.currentTimeMillis() + ".jpg"; 33 | File file = new File(appDir, fileName); 34 | try { 35 | FileOutputStream fos = new FileOutputStream(file); 36 | bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos); 37 | fos.flush(); 38 | fos.close(); 39 | } catch (FileNotFoundException e) { 40 | e.printStackTrace(); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | // 最后通知图库更新 46 | context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file))); 47 | } 48 | 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/utils/Constant.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * Description: 常量 5 | * Author:pz 6 | * Date:2016/10/24:14:18 7 | */ 8 | public class Constant { 9 | 10 | public static final String IMAGE_URL="image"; 11 | public static final String IMAGE_URL_ALL="images"; 12 | public static final String BASE_URL="http://news.sina.com.cn/"; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/utils/ImageLoaderUtils.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.graphics.Bitmap; 6 | import android.net.Uri; 7 | import android.util.Log; 8 | import android.widget.ImageView; 9 | import android.widget.Toast; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.bumptech.glide.load.resource.drawable.GlideDrawable; 13 | import com.bumptech.glide.request.animation.GlideAnimation; 14 | import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; 15 | import com.peng.zhang.activity.R; 16 | 17 | import java.io.File; 18 | import java.io.FileOutputStream; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.util.Date; 22 | 23 | import api.ApiManager; 24 | import okhttp3.Response; 25 | import okhttp3.ResponseBody; 26 | import rx.Observer; 27 | import rx.android.schedulers.AndroidSchedulers; 28 | import rx.schedulers.Schedulers; 29 | import uk.co.senab.photoview.PhotoViewAttacher; 30 | 31 | /** 32 | * description:图片加载工具类 33 | * author:pz 34 | * data:2016/10/24 35 | */ 36 | public class ImageLoaderUtils { 37 | 38 | public static void displayScaleImage(Context context, final ImageView imageView, String url, final PhotoViewAttacher photoViewAttacher) { 39 | if (imageView == null) { 40 | throw new IllegalArgumentException("argument error"); 41 | } 42 | 43 | Glide.with(context). 44 | load(url) 45 | .placeholder(R.drawable.avatar_default) 46 | .error(R.drawable.image_default_rect) 47 | .into(new GlideDrawableImageViewTarget(imageView) { 48 | @Override 49 | public void onResourceReady(GlideDrawable resource, GlideAnimation animation) { 50 | super.onResourceReady(resource, animation); 51 | if (photoViewAttacher != null) { 52 | photoViewAttacher.update(); 53 | } 54 | } 55 | }); 56 | } 57 | 58 | public static void downLoadImage(final String url, final String destFileDir,final Context context) { 59 | ApiManager.getInstance().getApiService().downLoadImage(url) 60 | .subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()) 62 | .subscribe(new Observer() { 63 | @Override 64 | public void onCompleted() { 65 | 66 | } 67 | 68 | @Override 69 | public void onError(Throwable e) { 70 | ToastManager.show("保存失败"); 71 | } 72 | 73 | @Override 74 | public void onNext(ResponseBody responseBody) { 75 | InputStream is = null; 76 | byte[] buf = new byte[2048]; 77 | int len = 0; 78 | FileOutputStream fos = null; 79 | try { 80 | is = responseBody.byteStream(); 81 | File file = new File(destFileDir); 82 | //如果file不存在,就创建这个file 83 | if (!file.exists()) { 84 | file.mkdir(); 85 | } 86 | 87 | final File imageFile = new File(destFileDir, new Date().getTime() + ".jpg"); 88 | fos = new FileOutputStream(imageFile); 89 | while ((len = is.read(buf)) != -1) { 90 | fos.write(buf, 0, len); 91 | } 92 | fos.flush(); 93 | ToastManager.show("保存成功"); 94 | //更新相册 95 | Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 96 | Uri uri = Uri.fromFile(file); 97 | intent.setData(uri); 98 | context.sendBroadcast(intent); 99 | 100 | } catch (IOException e) { 101 | e.printStackTrace(); 102 | ToastManager.show("保存失败"); 103 | } finally { 104 | try { 105 | if (is != null) is.close(); 106 | } catch (IOException e) { 107 | } 108 | try { 109 | if (fos != null) fos.close(); 110 | } catch (IOException e) { 111 | } 112 | } 113 | 114 | } 115 | }); 116 | } 117 | 118 | 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/utils/SystemApplication.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | 6 | /** 7 | * Description: 8 | * Author:pz 9 | * Date:2016/10/24:15:14 10 | */ 11 | public class SystemApplication extends Application{ 12 | private static Context context; 13 | @Override 14 | public void onCreate() { 15 | super.onCreate(); 16 | context = getApplicationContext(); 17 | } 18 | 19 | public static Context getContext(){ 20 | return context; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/utils/ToastManager.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | /** 11 | * Toast 12 | */ 13 | public class ToastManager { 14 | private static Toast toast = null; 15 | 16 | public static void showError(String msg) { 17 | Context context =SystemApplication.getContext(); 18 | toast = Toast.makeText(context, msg, Toast.LENGTH_LONG); 19 | toast.setGravity(Gravity.BOTTOM, 0, 200); 20 | View view = toast.getView(); 21 | TextView tv = (TextView) view.findViewById(android.R.id.message); 22 | view.setBackgroundColor(0xb0000000); 23 | tv.setSingleLine(true); 24 | tv.setTextColor(Color.parseColor("#FFFFFF")); 25 | // tv.setTextSize(); 26 | toast.show(); 27 | } 28 | 29 | public static void show(String msg) { 30 | Context context = SystemApplication.getContext(); 31 | toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); 32 | toast.setGravity(Gravity.BOTTOM, 0, 200); 33 | View view = toast.getView(); 34 | TextView tv = (TextView) view.findViewById(android.R.id.message); 35 | tv.setGravity(Gravity.CENTER); 36 | //view.setBackgroundColor(0xb0000000); 37 | tv.setSingleLine(false); 38 | tv.setTextColor(Color.parseColor("#FFFFFF")); 39 | // tv.setTextColor(context.getResources().getColor(R.color.font_color)); 40 | // tv.setTextSize(); 41 | toast.show(); 42 | } 43 | 44 | public void cancle() { 45 | if (toast != null) { 46 | toast.cancel(); 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/view/ActionSheetDialog.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.view.Display; 7 | import android.view.Gravity; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | import android.widget.LinearLayout; 13 | import android.widget.ScrollView; 14 | import android.widget.TextView; 15 | 16 | 17 | import com.peng.zhang.activity.R; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * description: 自定义多选 dialog 24 | * author:pz 25 | * 时间:2016/10/23 :22:13 26 | */ 27 | public class ActionSheetDialog { 28 | private Context context; 29 | private Dialog dialog; 30 | private TextView txt_title; 31 | private TextView txt_cancel; 32 | private LinearLayout lLayout_content; 33 | private ScrollView sLayout_content; 34 | private boolean showTitle = false; 35 | private List sheetItemList; 36 | private Display display; 37 | 38 | public ActionSheetDialog(Context context) { 39 | this.context = context; 40 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 41 | display = windowManager.getDefaultDisplay(); 42 | } 43 | 44 | @SuppressWarnings("deprecation") 45 | public ActionSheetDialog builder() { 46 | // 获取Dialog布局 47 | View view = LayoutInflater.from(context).inflate(R.layout.toast_view_actionsheet, null); 48 | 49 | // 设置Dialog最小宽度为屏幕宽度 50 | view.setMinimumWidth(display.getWidth()); 51 | 52 | // 获取自定义Dialog布局中的控件 53 | sLayout_content = (ScrollView) view.findViewById(R.id.sLayout_content); 54 | lLayout_content = (LinearLayout) view.findViewById(R.id.lLayout_content); 55 | txt_title = (TextView) view.findViewById(R.id.txt_title); 56 | txt_cancel = (TextView) view.findViewById(R.id.txt_cancel); 57 | txt_cancel.setOnClickListener(new View.OnClickListener() { 58 | @Override 59 | public void onClick(View v) { 60 | dialog.dismiss(); 61 | } 62 | }); 63 | 64 | // 定义Dialog布局和参数 65 | dialog = new Dialog(context, R.style.ActionSheetDialogStyle); 66 | dialog.setContentView(view); 67 | Window dialogWindow = dialog.getWindow(); 68 | dialogWindow.setGravity(Gravity.LEFT | Gravity.BOTTOM); 69 | WindowManager.LayoutParams lp = dialogWindow.getAttributes(); 70 | lp.x = 0; 71 | lp.y = 0; 72 | dialogWindow.setAttributes(lp); 73 | 74 | return this; 75 | } 76 | 77 | public ActionSheetDialog setTitle(String title) { 78 | showTitle = true; 79 | txt_title.setVisibility(View.VISIBLE); 80 | txt_title.setText(title); 81 | return this; 82 | } 83 | 84 | public ActionSheetDialog setCancelable(boolean cancel) { 85 | dialog.setCancelable(cancel); 86 | return this; 87 | } 88 | 89 | public ActionSheetDialog setCanceledOnTouchOutside(boolean cancel) { 90 | dialog.setCanceledOnTouchOutside(cancel); 91 | return this; 92 | } 93 | 94 | /** 95 | * @param strItem 条目名称 96 | * @param color 条目字体颜色,设置null则默认蓝色 97 | * @param listener 98 | * @return 99 | */ 100 | public ActionSheetDialog addSheetItem(String strItem, SheetItemColor color, 101 | OnSheetItemClickListener listener) { 102 | if (sheetItemList == null) { 103 | sheetItemList = new ArrayList<>(); 104 | } 105 | sheetItemList.add(new SheetItem(strItem, color, listener)); 106 | return this; 107 | } 108 | 109 | /** 110 | * 设置条目布局 111 | */ 112 | @SuppressWarnings("deprecation") 113 | private void setSheetItems() { 114 | if (sheetItemList == null || sheetItemList.size() <= 0) { 115 | return; 116 | } 117 | 118 | int size = sheetItemList.size(); 119 | 120 | // TODO 高度控制,非最佳解决办法 121 | // 添加条目过多的时候控制高度 122 | if (size >= 7) { 123 | LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) sLayout_content.getLayoutParams(); 124 | params.height = display.getHeight() / 2; 125 | sLayout_content.setLayoutParams(params); 126 | } 127 | 128 | // 循环添加条目 129 | for (int i = 1; i <= size; i++) { 130 | final int index = i; 131 | SheetItem sheetItem = sheetItemList.get(i - 1); 132 | String strItem = sheetItem.name; 133 | SheetItemColor color = sheetItem.color; 134 | final OnSheetItemClickListener listener = sheetItem.itemClickListener; 135 | 136 | TextView textView = new TextView(context); 137 | textView.setText(strItem); 138 | textView.setTextSize(18); 139 | textView.setGravity(Gravity.CENTER); 140 | 141 | // 背景图片 142 | if (size == 1) { 143 | if (showTitle) { 144 | textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); 145 | } else { 146 | textView.setBackgroundResource(R.drawable.actionsheet_single_selector); 147 | } 148 | } else { 149 | if (showTitle) { 150 | if (i >= 1 && i < size) { 151 | textView.setBackgroundResource(R.drawable.actionsheet_middle_selector); 152 | } else { 153 | textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); 154 | } 155 | } else { 156 | if (i == 1) { 157 | textView.setBackgroundResource(R.drawable.actionsheet_top_selector); 158 | } else if (i < size) { 159 | textView.setBackgroundResource(R.drawable.actionsheet_middle_selector); 160 | } else { 161 | textView.setBackgroundResource(R.drawable.actionsheet_bottom_selector); 162 | } 163 | } 164 | } 165 | 166 | // 字体颜色 167 | if (color == null) { 168 | textView.setTextColor(Color.parseColor(SheetItemColor.Blue 169 | .getName())); 170 | } else { 171 | textView.setTextColor(Color.parseColor(color.getName())); 172 | } 173 | 174 | // 高度 175 | float scale = context.getResources().getDisplayMetrics().density; 176 | int height = (int) (45 * scale + 0.5f); 177 | textView.setLayoutParams(new LinearLayout.LayoutParams( 178 | LinearLayout.LayoutParams.MATCH_PARENT, height)); 179 | 180 | // 点击事件 181 | textView.setOnClickListener(new View.OnClickListener() { 182 | @Override 183 | public void onClick(View v) { 184 | listener.onClick(index); 185 | dialog.dismiss(); 186 | } 187 | }); 188 | 189 | lLayout_content.addView(textView); 190 | } 191 | } 192 | 193 | public void show() { 194 | setSheetItems(); 195 | dialog.show(); 196 | } 197 | 198 | public interface OnSheetItemClickListener { 199 | void onClick(int which); 200 | } 201 | 202 | public class SheetItem { 203 | String name; 204 | OnSheetItemClickListener itemClickListener; 205 | SheetItemColor color; 206 | 207 | public SheetItem(String name, SheetItemColor color, OnSheetItemClickListener itemClickListener) { 208 | this.name = name; 209 | this.color = color; 210 | this.itemClickListener = itemClickListener; 211 | } 212 | } 213 | 214 | public enum SheetItemColor { 215 | Blue("#037BFF"), Red("#FD4A2E"), Grey("#6c6c6c"); 216 | 217 | private String name; 218 | 219 | private SheetItemColor(String name) { 220 | this.name = name; 221 | } 222 | 223 | public String getName() { 224 | return name; 225 | } 226 | 227 | public void setName(String name) { 228 | this.name = name; 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /app/src/main/java/view/PhotoViewViewPager.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * description:处理缩放时的崩溃问题 10 | * author:pz 11 | * 时间:2016/10/14:22:42 12 | */ 13 | public class PhotoViewViewPager extends ViewPager { 14 | public PhotoViewViewPager(Context context) { 15 | super(context); 16 | } 17 | 18 | public PhotoViewViewPager(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | } 21 | 22 | @Override 23 | public boolean onInterceptTouchEvent(MotionEvent ev) { 24 | try { 25 | return super.onInterceptTouchEvent(ev); 26 | } catch (IllegalArgumentException e) { 27 | e.printStackTrace(); 28 | return false; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/view/ShowImageWebView.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Environment; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.webkit.WebView; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.regex.Matcher; 13 | import java.util.regex.Pattern; 14 | 15 | import activity.ShowImageFromWebActivity; 16 | import utils.Constant; 17 | import utils.ImageLoaderUtils; 18 | 19 | /** 20 | * 可以实现点击图片进行保存的 WebView 21 | * Created by FZT on 2016/10/10. 22 | */ 23 | public class ShowImageWebView extends WebView { 24 | 25 | private List listImgSrc = new ArrayList<>(); 26 | // 获取img标签正则 27 | private static final String IMAGE_URL_TAG = "]*?>"; 28 | // 获取src路径的正则 29 | private static final String IMAGE_URL_CONTENT = "http:\"?(.*?)(\"|>|\\s+)"; 30 | 31 | private String url; 32 | private String longClickUrl; 33 | private Context context; 34 | 35 | public ShowImageWebView(Context context) { 36 | super(context); 37 | init(context); 38 | } 39 | 40 | public ShowImageWebView(Context context, AttributeSet attrs) { 41 | super(context, attrs); 42 | init(context); 43 | } 44 | 45 | public ShowImageWebView(Context context, AttributeSet attrs, int defStyleAttr) { 46 | super(context, attrs, defStyleAttr); 47 | init(context); 48 | } 49 | 50 | private void init(Context context){ 51 | this.context=context; 52 | this.setOnLongClickListener(new OnLongClickListener() { 53 | @Override 54 | public boolean onLongClick(View v) { 55 | setWebImageLongClickListener(v); 56 | return false; 57 | } 58 | }); 59 | 60 | this.getSettings().setJavaScriptEnabled(true); 61 | this.getSettings().setDefaultTextEncodingName("UTF -8"); 62 | 63 | //载入js 64 | this.addJavascriptInterface(new MyJavascriptInterface(context), "imageListener"); 65 | //获取 html 66 | this.addJavascriptInterface(new InJavaScriptLocalObj(), "local_obj"); 67 | } 68 | 69 | /** 70 | * 响应长按点击事件 71 | * @param v 72 | */ 73 | private void setWebImageLongClickListener(View v) { 74 | if (v instanceof WebView) { 75 | HitTestResult result = ((WebView) v).getHitTestResult(); 76 | if (result != null) { 77 | int type = result.getType(); 78 | if (type == HitTestResult.IMAGE_TYPE || type == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { 79 | longClickUrl = result.getExtra(); 80 | showDialog(longClickUrl); 81 | } 82 | } 83 | } 84 | } 85 | 86 | /** 87 | * 解析 HTML 该方法在 setWebViewClient 的 onPageFinished 方法中进行调用 88 | * @param view 89 | */ 90 | public void parseHTML(WebView view) { 91 | view.loadUrl("javascript:window.local_obj.showSource(''+" 92 | + "document.getElementsByTagName('html')[0].innerHTML+'');"); 93 | } 94 | 95 | /** 96 | * 注入 js 函数监听,这段 js 函数的功能就是,遍历所有的图片,并添加 onclick 函数,实现点击事件, 97 | * 函数的功能是在图片点击的时候调用本地java接口并传递 url 过去 98 | */ 99 | public void setImageClickListner() { 100 | // 这段js函数的功能就是,遍历所有的img几点,并添加onclick函数,函数的功能是在图片点击的时候调用本地java接口并传递url过去 101 | this.loadUrl("javascript:(function(){" + 102 | "var objs = document.getElementsByTagName(\"img\"); " + 103 | "for(var i=0;i) listImgSrc); 131 | intent.setClass(context, ShowImageFromWebActivity.class); 132 | context.startActivity(intent); 133 | } 134 | } 135 | 136 | private class InJavaScriptLocalObj { 137 | /** 138 | * 获取要解析 WebView 加载对应的 Html 文本 139 | * 140 | * @param html WebView 加载对应的 Html 文本 141 | */ 142 | @android.webkit.JavascriptInterface 143 | public void showSource(String html) { 144 | //从 Html 文件中提取页面所有图片对应的地址对象 145 | getAllImageUrlFromHtml(html); 146 | } 147 | } 148 | 149 | /*** 150 | * 获取页面所有图片对应的地址对象, 151 | * 例如 152 | * 153 | * @param html WebView 加载的 html 文本 154 | * @return 155 | */ 156 | private List getAllImageUrlFromHtml(String html) { 157 | Matcher matcher = Pattern.compile(IMAGE_URL_TAG).matcher(html); 158 | List listImgUrl = new ArrayList(); 159 | while (matcher.find()) { 160 | listImgUrl.add(matcher.group()); 161 | } 162 | //从图片对应的地址对象中解析出 src 标签对应的内容 163 | getAllImageUrlFormSrcObject(listImgUrl); 164 | return listImgUrl; 165 | } 166 | 167 | /*** 168 | * 从图片对应的地址对象中解析出 src 标签对应的内容,即 url 169 | * 例如 "http://sc1.hao123img.com/data/f44d0aab7bc35b8767de3c48706d429e" 170 | * @param listImageUrl 图片地址对象, 171 | * 例如 172 | */ 173 | private List getAllImageUrlFormSrcObject(List listImageUrl) { 174 | for (String image : listImageUrl) { 175 | Matcher matcher = Pattern.compile(IMAGE_URL_CONTENT).matcher(image); 176 | while (matcher.find()) { 177 | listImgSrc.add(matcher.group().substring(0, matcher.group().length() - 1)); 178 | } 179 | } 180 | return listImgSrc; 181 | } 182 | 183 | /** 184 | * 长按 WebView 图片弹出 Dialog 185 | * @param url 186 | */ 187 | private void showDialog(final String url) { 188 | new ActionSheetDialog(context) 189 | .builder() 190 | .setCancelable(true) 191 | .setCanceledOnTouchOutside(true) 192 | .addSheetItem( 193 | "保存到相册", 194 | ActionSheetDialog.SheetItemColor.Blue, 195 | new ActionSheetDialog.OnSheetItemClickListener() { 196 | @Override 197 | public void onClick(int which) { 198 | downloadImage(url); 199 | } 200 | }).show(); 201 | } 202 | 203 | /** 204 | * 开始下载图片 205 | */ 206 | private void downloadImage(String url) { 207 | ImageLoaderUtils.downLoadImage(url,Environment.getExternalStorageDirectory().getAbsolutePath() + "/ImagesFromWebView",context); 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /app/src/main/res/anim/actionsheet_dialog_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/anim/actionsheet_dialog_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/avatar_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/avatar_default.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/image_default_rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/image_default_rect.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_bottom_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_bottom_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_bottom_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_bottom_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_middle_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_middle_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_middle_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_middle_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_single_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_single_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_single_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_single_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_top_normal.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_top_normal.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/toast_actionsheet_top_pressed.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yongyu0102/ShowImageFromWebView/0e109e103a1965ef6da2edde95cc7bab975632f5/app/src/main/res/drawable-xhdpi/toast_actionsheet_top_pressed.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/actionsheet_bottom_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/actionsheet_middle_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/actionsheet_single_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/actionsheet_top_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_corner_rect_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_show_image_from_web.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 12 | 13 | 14 | 20 | 33 | 34 | 35 | 36 | 40 |