效果图:

aaarticlea/png;base64,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" alt="" />

类ImageLoader.class:

/*******************************************************************************
* Copyright 2011-2013 Sergey Tarasevich
*
* 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.nostra13.universalimageloader.core; import android.graphics.Bitmap;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import com.nostra13.universalimageloader.cache.disc.DiscCacheAware;
import com.nostra13.universalimageloader.cache.memory.MemoryCacheAware;
import com.nostra13.universalimageloader.core.assist.*;
import com.nostra13.universalimageloader.core.display.BitmapDisplayer;
import com.nostra13.universalimageloader.core.display.FakeBitmapDisplayer;
import com.nostra13.universalimageloader.utils.ImageSizeUtils;
import com.nostra13.universalimageloader.utils.L; /**
* Singletone for image loading and displaying at {@link ImageView ImageViews}<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before any other method.
*
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @since 1.0.0
*/
public class ImageLoader { public static final String TAG = ImageLoader.class.getSimpleName(); static final String LOG_INIT_CONFIG = "Initialize ImageLoader with configuration";
static final String LOG_DESTROY = "Destroy ImageLoader";
static final String LOG_LOAD_IMAGE_FROM_MEMORY_CACHE = "Load image from memory cache [%s]"; private static final String WARNING_RE_INIT_CONFIG = "Try to initialize ImageLoader which had already been initialized before. "
+ "To re-init ImageLoader with new configuration call ImageLoader.destroy() at first.";
private static final String ERROR_WRONG_ARGUMENTS = "Wrong arguments were passed to displayImage() method (ImageView reference must not be null)";
private static final String ERROR_NOT_INIT = "ImageLoader must be init with configuration before using";
private static final String ERROR_INIT_CONFIG_WITH_NULL = "ImageLoader configuration can not be initialized with null"; private ImageLoaderConfiguration configuration;
private ImageLoaderEngine engine; private final ImageLoadingListener emptyListener = new SimpleImageLoadingListener();
private final BitmapDisplayer fakeBitmapDisplayer = new FakeBitmapDisplayer(); private volatile static ImageLoader instance; /** Returns singleton class instance */
public static ImageLoader getInstance() {
if (instance == null) {
synchronized (ImageLoader.class) {
if (instance == null) {
instance = new ImageLoader();
}
}
}
return instance;
} protected ImageLoader() {
} /**
* Initializes ImageLoader instance with configuration.<br />
* If configurations was set before ( {@link #isInited()} == true) then this method does nothing.<br />
* To force initialization with new configuration you should {@linkplain #destroy() destroy ImageLoader} at first.
*
* @param configuration {@linkplain ImageLoaderConfiguration ImageLoader configuration}
* @throws IllegalArgumentException if <b>configuration</b> parameter is null
*/
public synchronized void init(ImageLoaderConfiguration configuration) {
if (configuration == null) {
throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL);
}
if (this.configuration == null) {
if (configuration.writeLogs) L.d(LOG_INIT_CONFIG);
engine = new ImageLoaderEngine(configuration);
this.configuration = configuration;
} else {
L.w(WARNING_RE_INIT_CONFIG);
}
} /**
* Returns <b>true</b> - if ImageLoader {@linkplain #init(ImageLoaderConfiguration) is initialized with
* configuration}; <b>false</b> - otherwise
*/
public boolean isInited() {
return configuration != null;
} /**
* Adds display image task to execution pool. Image will be set to ImageView when it's turn. <br/>
* Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration
* configuration} will be used.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param imageView {@link ImageView} which should display image
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @throws IllegalArgumentException if passed <b>imageView</b> is null
*/
public void displayImage(String uri, ImageView imageView) {
displayImage(uri, imageView, null, null);
} /**
* Adds display image task to execution pool. Image will be set to ImageView when it's turn.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param imageView {@link ImageView} which should display image
* @param options {@linkplain DisplayImageOptions Display image options} for image displaying. If <b>null</b> -
* default display image options
* {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from
* configuration} will be used.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @throws IllegalArgumentException if passed <b>imageView</b> is null
*/
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options) {
displayImage(uri, imageView, options, null);
} /**
* Adds display image task to execution pool. Image will be set to ImageView when it's turn.<br />
* Default {@linkplain DisplayImageOptions display image options} from {@linkplain ImageLoaderConfiguration
* configuration} will be used.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param imageView {@link ImageView} which should display image
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @throws IllegalArgumentException if passed <b>imageView</b> is null
*/
public void displayImage(String uri, ImageView imageView, ImageLoadingListener listener) {
displayImage(uri, imageView, null, listener);
} /**
* Adds display image task to execution pool. Image will be set to ImageView when it's turn.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param imageView {@link ImageView} which should display image
* @param options {@linkplain DisplayImageOptions Display image options} for image displaying. If <b>null</b> -
* default display image options
* {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from
* configuration} will be used.
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
* @throws IllegalArgumentException if passed <b>imageView</b> is null
*/
public void displayImage(String uri, ImageView imageView, DisplayImageOptions options, ImageLoadingListener listener) {
checkConfiguration();
if (imageView == null) {
throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);
}
if (listener == null) {
listener = emptyListener;
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
} if (TextUtils.isEmpty(uri)) {
engine.cancelDisplayTaskFor(imageView);
listener.onLoadingStarted(uri, imageView);
if (options.shouldShowImageForEmptyUri()) {
imageView.setImageResource(options.getImageForEmptyUri());
} else {
imageView.setImageDrawable(null);
}
listener.onLoadingComplete(uri, imageView, null);
return;
} ImageSize targetSize = ImageSizeUtils.defineTargetSizeForView(imageView, configuration.maxImageWidthForMemoryCache, configuration.maxImageHeightForMemoryCache);
String memoryCacheKey = MemoryCacheUtil.generateKey(uri, targetSize);
engine.prepareDisplayTaskFor(imageView, memoryCacheKey); listener.onLoadingStarted(uri, imageView);
Bitmap bmp = configuration.memoryCache.get(memoryCacheKey);
if (bmp != null && !bmp.isRecycled()) {
if (configuration.writeLogs) L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey); if (options.shouldPostProcess()) {
ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo, options.getHandler());
engine.submit(displayTask);
} else {
options.getDisplayer().display(bmp, imageView, LoadedFrom.MEMORY_CACHE);
listener.onLoadingComplete(uri, imageView, bmp);
}
} else {
if (options.shouldShowStubImage()) {
imageView.setImageResource(options.getStubImage());
} else {
if (options.isResetViewBeforeLoading()) {
imageView.setImageDrawable(null);
}
} ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageView, targetSize, memoryCacheKey, options, listener, engine.getLockForUri(uri));
LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo, options.getHandler());
engine.submit(displayTask);
}
} /**
* Adds load image task to execution pool. Image will be returned with
* {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void loadImage(String uri, ImageLoadingListener listener) {
loadImage(uri, null, null, listener);
} /**
* Adds load image task to execution pool. Image will be returned with
* {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param minImageSize Minimal size for {@link Bitmap} which will be returned in
* {@linkplain ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. Downloaded image will be decoded
* and scaled to {@link Bitmap} of the size which is <b>equal or larger</b> (usually a bit larger) than
* incoming minImageSize .
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void loadImage(String uri, ImageSize minImageSize, ImageLoadingListener listener) {
loadImage(uri, minImageSize, null, listener);
} /**
* Adds load image task to execution pool. Image will be returned with
* {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param options {@linkplain DisplayImageOptions Display image options} for image displaying. If <b>null</b> -
* default display image options
* {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from
* configuration} will be used.<br />
* Incoming options should contain {@link FakeBitmapDisplayer} as displayer.
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void loadImage(String uri, DisplayImageOptions options, ImageLoadingListener listener) {
loadImage(uri, null, options, listener);
} /**
* Adds load image task to execution pool. Image will be returned with
* {@link ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}.<br />
* <b>NOTE:</b> {@link #init(ImageLoaderConfiguration)} method must be called before this method call
*
* @param uri Image URI (i.e. "http://site.com/image.png", "file:///mnt/sdcard/image.png")
* @param targetImageSize Minimal size for {@link Bitmap} which will be returned in
* {@linkplain ImageLoadingListener#onLoadingComplete(String, android.view.View, android.graphics.Bitmap)} callback}. Downloaded image will be decoded
* and scaled to {@link Bitmap} of the size which is <b>equal or larger</b> (usually a bit larger) than
* incoming minImageSize .
* @param options {@linkplain DisplayImageOptions Display image options} for image displaying. If <b>null</b> -
* default display image options
* {@linkplain ImageLoaderConfiguration.Builder#defaultDisplayImageOptions(DisplayImageOptions) from
* configuration} will be used.<br />
* Incoming options should contain {@link FakeBitmapDisplayer} as displayer.
* @param listener {@linkplain ImageLoadingListener Listener} for image loading process. Listener fires events on UI
* thread.
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void loadImage(String uri, ImageSize targetImageSize, DisplayImageOptions options, ImageLoadingListener listener) {
checkConfiguration();
if (targetImageSize == null) {
targetImageSize = new ImageSize(configuration.maxImageWidthForMemoryCache, configuration.maxImageHeightForMemoryCache);
}
if (options == null) {
options = configuration.defaultDisplayImageOptions;
} DisplayImageOptions optionsWithFakeDisplayer;
if (options.getDisplayer() instanceof FakeBitmapDisplayer) {
optionsWithFakeDisplayer = options;
} else {
optionsWithFakeDisplayer = new DisplayImageOptions.Builder().cloneFrom(options).displayer(fakeBitmapDisplayer).build();
} ImageView fakeImage = new ImageView(configuration.context);
fakeImage.setLayoutParams(new LayoutParams(targetImageSize.getWidth(), targetImageSize.getHeight()));
fakeImage.setScaleType(ScaleType.CENTER_CROP); displayImage(uri, fakeImage, optionsWithFakeDisplayer, listener);
} /**
* Checks if ImageLoader's configuration was initialized
*
* @throws IllegalStateException if configuration wasn't initialized
*/
private void checkConfiguration() {
if (configuration == null) {
throw new IllegalStateException(ERROR_NOT_INIT);
}
} /**
* Returns memory cache
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public MemoryCacheAware<String, Bitmap> getMemoryCache() {
checkConfiguration();
return configuration.memoryCache;
} /**
* Clears memory cache
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void clearMemoryCache() {
checkConfiguration();
configuration.memoryCache.clear();
} /**
* Returns disc cache
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public DiscCacheAware getDiscCache() {
checkConfiguration();
return configuration.discCache;
} /**
* Clears disc cache.
*
* @throws IllegalStateException if {@link #init(ImageLoaderConfiguration)} method wasn't called before
*/
public void clearDiscCache() {
checkConfiguration();
configuration.discCache.clear();
} /** Returns URI of image which is loading at this moment into passed {@link ImageView} */
public String getLoadingUriForView(ImageView imageView) {
return engine.getLoadingUriForView(imageView);
} /**
* Cancel the task of loading and displaying image for passed {@link ImageView}.
*
* @param imageView {@link ImageView} for which display task will be cancelled
*/
public void cancelDisplayTask(ImageView imageView) {
engine.cancelDisplayTaskFor(imageView);
} /**
* Denies or allows ImageLoader to download images from the network.<br />
* <br />
* If downloads are denied and if image isn't cached then
* {@link ImageLoadingListener#onLoadingFailed(String, View, FailReason)} callback will be fired with
* {@link FailReason.FailType#NETWORK_DENIED}
*
* @param denyNetworkDownloads pass <b>true</b> - to deny engine to download images from the network; <b>false</b> -
* to allow engine to download images from network.
*/
public void denyNetworkDownloads(boolean denyNetworkDownloads) {
engine.denyNetworkDownloads(denyNetworkDownloads);
} /**
* Sets option whether ImageLoader will use {@link FlushedInputStream} for network downloads to handle <a
* href="http://code.google.com/p/android/issues/detail?id=6066">this known problem</a> or not.
*
* @param handleSlowNetwork pass <b>true</b> - to use {@link FlushedInputStream} for network downloads; <b>false</b>
* - otherwise.
*/
public void handleSlowNetwork(boolean handleSlowNetwork) {
engine.handleSlowNetwork(handleSlowNetwork);
} /**
* Pause ImageLoader. All new "load&display" tasks won't be executed until ImageLoader is {@link #resume() resumed}.<br />
* Already running tasks are not paused.
*/
public void pause() {
engine.pause();
} /** Resumes waiting "load&display" tasks */
public void resume() {
engine.resume();
} /**
* Cancels all running and scheduled display image tasks.<br />
* ImageLoader still can be used after calling this method.
*/
public void stop() {
engine.stop();
} /**
* {@linkplain #stop() Stops ImageLoader} and clears current configuration. <br />
* You can {@linkplain #init(ImageLoaderConfiguration) init} ImageLoader with new configuration after calling this
* method.
*/
public void destroy() {
if (configuration != null && configuration.writeLogs) L.d(LOG_DESTROY);
stop();
engine = null;
configuration = null;
}
}

调用方法:

public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.menu_about: break; case R.id.menu_setting: break; case R.id.menu_history: break; case R.id.menu_feedback: break; case R.id.menu_exit: showAlertDialog("退出程序", "确定退出高仿京东商城?", "确定", new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
AppManager.getInstance().AppExit(getApplicationContext());
ImageLoader.getInstance().clearMemoryCache();
}
}, "取消", new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
}); break; case R.id.menu_help: break; default:
break;
}
return true;
}

出自:高仿京东商城

Android 黑色样式menu的更多相关文章

  1. Android ActionBar以及menu的代码设置样式

    menu部分xml代码 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android= ...

  2. Android Studio —— 创建Menu菜单项

    大多数android程序的右上角都会设置一个菜单按钮比如微信的界面右上角的加号. 这个需要在layout同级目录下新建文件夹命名为menu,再右击新建的menu新建xml文件:

  3. android自定义样式大全:shape,selector,layer-list,style,动画全部内容

    原文:http://keeganlee.me/post/android/20150830 以下摘取了部分内容: shape 一般用shape定义的xml文件存放在drawable目录下,若项目没有该目 ...

  4. Android菜单详解(一)——理解android中的Menu

    前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...

  5. android studio样式文件汇总

    android studio样式文件汇总:shape.Theme|styles .selector 1:shape shape用于设定形状,有6个子标签,各属性如下: res/drawable/sty ...

  6. Android spinner 样式及其使用详解

    设计与开发首页 > 应用专题 > 移动开发 > 正文> Android spinner 样式及其使用详解 相关文章: Android 开源项目应用程序与框架推荐 Android ...

  7. android 开发-(Contextual Menu)上下文菜单的实现

    在android3.0以后,安卓设备不在提供物理的菜单按键,同时,android应用提供了另外的菜单实现机制,来替代之前的菜单创建方式.安卓设备中,平常可以使用长按住某个内容弹出菜单选项.这就是我们需 ...

  8. 这些Android系统样式中的颜色属性你知道吗?

    Android 系统样式中的颜色属性 推荐阅读看完后彻底搞清楚Android中的 Attr . Style .Theme 几个常用的颜色属性 先放上一张经典的图片,图片来自网络. 这张图在网上很是流传 ...

  9. Android Toolbar样式定制详解

    前言 Marterial Design出来也有一段时间了,为了紧跟Google的设计规范,决定在项目中使用Toolbar.使用了一段时间之后,发现很多时候原始的Toolbar并不能满足项目的要求.为了 ...

随机推荐

  1. [BZOJ 5072][Lydsy1710月赛]小A的树

    传送门 \(\color{green}{solution}\) 嗯...其实我也不太会,所以大胆猜个结论吧(后来证了一下,然后放弃了...). 我们发现如果要使一个联通块的黑点数量为\(k\)的方案最 ...

  2. ospf基础理论

    OSPF简介 OSPF(Open Shortest Path First 开放式最短路径优先)协议是IETF为IP网络开发的IGP路由选择协议.它是一种典型的链路状态(link-state)路由协议. ...

  3. 内存溢出(Oom)和内存泄露(Memory leak)

    1.概念 内存溢出(Oom):1.内存不够用:2.数据长度短的数据类型存储了一个数据长度较大的数据类型:3.一个结果 内存泄露(Memory leak):1.忘记释放已用内存,内存管理较为常见的现象: ...

  4. IDEA Maven Mybatis generator 自动生成代码

    IDEA Maven Mybatis generator 自动生成代码 一.安装配置maven以及在Idea中配置maven 安装过程步骤可以看上面的博文,里面介绍得很详细. 二.建数据表 DROP ...

  5. Chapter 6. Names

    6.2. Names and Identifiers A name is used to refer to an entity declared in a program. There are two ...

  6. 关于chrome下的bug

    最近看了大神的一篇文章,于是尝试了一下里面说的bug以及修复 1.Chrome下absolute绝对定位元素部分display属性值不渲染bug 首先还原一下bug.. ff下的下效果 点击按钮后的效 ...

  7. Critical Regions和Guarded Regions区别

    KeEnterCriticalRegion和KeLeaveCriticalRegion配合使用,能禁止用户模式APC和普通内核模式APC的调用,但是不能禁止特殊内核模式的调用(NormalRoutin ...

  8. [作业] Python入门基础--猜年龄

    age = 20 while True: try: guess_age = int(input('guess age:')) if guess_age > age: print('Is bigg ...

  9. java调用ruby代码

    问题: 最近在做一个应用的时候碰到了一个问题.客户端需要调用服务器端传回的脚本信息,然后执行.其中脚本类型包括ruby.而java中调用ruby的代码大致如下: String jrubyCode=&q ...

  10. Android 直接通过JNI访问驱动

    package com.yang.jniaccesshardware; import android.os.Bundle; import android.support.v7.app.AppCompa ...