編輯:關於Android編程
主要分析官方的demo,以及一些需要注意的東西
1,首先,三個頁面
HomeActivity(首頁,注意有清空緩存的菜單鍵)
SimpleImageActivity(listview,gridview,gallery,viewpage等都在此頁面,通過不同的fragment顯示)
ComplexImageActivity(通過viewpage混和了listview和gridview的頁面)
首頁
/*******************************************************************************
* 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.sample.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageListFragment;
import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment;
import com.nostra13.universalimageloader.utils.L;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class HomeActivity extends Activity {
private static final String TEST_FILE_NAME = Universal Image Loader @#&=+-_.,!()~'%20.png;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_home);
File testImageOnSdCard = new File(/mnt/sdcard, TEST_FILE_NAME);
if (!testImageOnSdCard.exists()) {
copyTestImageToSdCard(testImageOnSdCard);
}
}
public void onImageListClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageListFragment.INDEX);
startActivity(intent);
}
public void onImageGridClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGridFragment.INDEX);
startActivity(intent);
}
public void onImagePagerClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX);
startActivity(intent);
}
public void onImageGalleryClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGalleryFragment.INDEX);
startActivity(intent);
}
public void onFragmentsClick(View view) {
Intent intent = new Intent(this, ComplexImageActivity.class);
startActivity(intent);
}
@Override
public void onBackPressed() {
ImageLoader.getInstance().stop();
super.onBackPressed();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_clear_memory_cache:
ImageLoader.getInstance().clearMemoryCache();
return true;
case R.id.item_clear_disc_cache:
ImageLoader.getInstance().clearDiskCache();
return true;
default:
return false;
}
}
private void copyTestImageToSdCard(final File testImageOnSdCard) {
new Thread(new Runnable() {
@Override
public void run() {
try {
InputStream is = getAssets().open(TEST_FILE_NAME);
FileOutputStream fos = new FileOutputStream(testImageOnSdCard);
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
} finally {
fos.flush();
fos.close();
is.close();
}
} catch (IOException e) {
L.w(Can't copy test image onto SD card);
}
}
}).start();
}
}
SimpleImageActivity
除了HomeActivity和ComplexImageActivity,其他界面都在此顯示
根據不同的標簽生成不同Fragment......最後commit,確認顯示
ImagePagerFragment標簽下需要保存下列表Fragment傳過來的條目position的數據,給ImagePagerFragment(實際上這個跳轉是從SimpleImageActivity跳到SimpleImageActivity,有點怪)
/*******************************************************************************
* Copyright 2014 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.sample.activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageListFragment;
import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
//除了主界面和組合了listview和gridview的界面,其他界面都在此顯示
//根據不同的標簽生成不同Fragment......最後commit,確認顯示
//ImagePagerFragment標簽下需要保存下列表Fragment傳過來的條目position的數據,給ImagePagerFragment(實際上這個跳轉是從SimpleImageActivity跳到SimpleImageActivity,有點怪)
public class SimpleImageActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int frIndex = getIntent().getIntExtra(Constants.Extra.FRAGMENT_INDEX, 0);
Fragment fr;
String tag;
int titleRes;
switch (frIndex) {
default:
case ImageListFragment.INDEX:
tag = ImageListFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageListFragment();
}
titleRes = R.string.ac_name_image_list;
break;
case ImageGridFragment.INDEX:
tag = ImageGridFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageGridFragment();
}
titleRes = R.string.ac_name_image_grid;
break;
case ImagePagerFragment.INDEX:
tag = ImagePagerFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImagePagerFragment();
fr.setArguments(getIntent().getExtras());
}
titleRes = R.string.ac_name_image_pager;
break;
case ImageGalleryFragment.INDEX:
tag = ImageGalleryFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageGalleryFragment();
}
titleRes = R.string.ac_name_image_gallery;
break;
}
setTitle(titleRes);
//此時關聯的tag和對應的fragment
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fr, tag).commit();
}
}
/*******************************************************************************
* Copyright 2014 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.sample.activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageListFragment;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ComplexImageActivity extends FragmentActivity {
private static final String STATE_POSITION = STATE_POSITION;
private ViewPager pager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_complex);
int pagerPosition = savedInstanceState == null ? 0 : savedInstanceState.getInt(STATE_POSITION);
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new ImagePagerAdapter(getSupportFragmentManager()));
pager.setCurrentItem(pagerPosition);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_POSITION, pager.getCurrentItem());
}
private class ImagePagerAdapter extends FragmentPagerAdapter {
Fragment listFragment;
Fragment gridFragment;
ImagePagerAdapter(FragmentManager fm) {
super(fm);
listFragment = new ImageListFragment();
gridFragment = new ImageGridFragment();
}
@Override
public int getCount() {
return 2;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return listFragment;
case 1:
return gridFragment;
default:
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.title_list);
case 1:
return getString(R.string.title_grid);
default:
return null;
}
}
}
}
可以配置默認的參數,並創建ImageLoader的實例
//創建默認的ImageLoader配置參數
ImageLoaderConfiguration configuration = ImageLoaderConfiguration
.createDefault(this);
//Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(configuration);
/*******************************************************************************
* 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.sample;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.StrictMode;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class UILApplication extends Application {
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@SuppressWarnings(unused)
@Override
public void onCreate() {
if (Constants.Config.DEVELOPER_MODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyDialog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build());
}
super.onCreate();
initImageLoader(getApplicationContext());
}
public static void initImageLoader(Context context) {
// This configuration tuning is custom. You can tune every option, you may tune some of them,
// or you can create default configuration by
// ImageLoaderConfiguration.createDefault(this);
// method.
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
//config.threadPoolSize(5) //設置線程池的最高線程數量(1-5)(減少線程個數,有利於減少發生OOM)
// 設置線程優先級(沒什麼用)
config.threadPriority(Thread.NORM_PRIORITY - 2);
// 設定內存緩存為弱緩存(該框架默認的緩存類是強引用緩存LruMemoryCache)
config.memoryCache(new WeakMemoryCache());
// 自動縮放
config.denyCacheImageMultipleSizesInMemory();
// 設定緩存到sd卡的文件的命名
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
// 設定緩存到sd卡的最大文件大小
config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
config.tasksProcessingOrder(QueueProcessingType.LIFO);
config.writeDebugLogs(); // Remove for release app
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config.build());
}
}
強引用是指創建一個對象並把這個對象賦給一個引用變量, 強引用有引用變量指向時永遠不會被垃圾回收。即使內存不足的時候寧願報OOM也不被垃圾回收器回收,我們new的對象都是強引用
弱引用通過weakReference類來實現,它具有很強的不確定性,如果垃圾回收器掃描到有著WeakReference的對象,就會將其回收釋放內存
本例的情況是
對於默認使用的強引用緩存(LruMemoryCache),采取的策略是,先進先出原則,設置一個固定緩存大小,當超出這個最大值時,刪除LinkedHashMap中的第一個元素
對於弱引用緩存(WeakMemoryCache),這個類緩存bitmap的總大小沒有限制,唯一不足的地方就是不穩定,緩存的圖片容易被回收掉
具體參考這篇分析詳細 http://blog.csdn.net/xiaanming/article/details/27525741
3,各個fragment
BaseFragment(用以給AbsListViewBaseFragment,ImageGalleryFragment,ImagePagerFragment繼承)(有兩個菜單項)
/*******************************************************************************
* Copyright 2011-2014 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.sample.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
//基礎Fragment,創建菜單兩項,清除內存緩存和清除硬盤緩存
public abstract class BaseFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_clear_memory_cache:
ImageLoader.getInstance().clearMemoryCache();
return true;
case R.id.item_clear_disc_cache:
ImageLoader.getInstance().clearDiskCache();
return true;
default:
return false;
}
}
}
主要有兩個關鍵的參數
//列表滾動是否暫停加載圖片
protected boolean pauseOnScroll = true;
//列表猛的滾動是否暫停加載圖片
protected boolean pauseOnFling = true;
/*******************************************************************************
* Copyright 2011-2014 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.sample.fragment;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AbsListView;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.activity.SimpleImageActivity;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
//要用於GridFragment和ListFragment,所以主要包括了通用的設置菜單方法,設置列表滑動是否暫停加載圖片的方法,以及傳遞item位置信息的方法
//因為gridview和listview都繼承自AbsListView,所以此類的listView也可以在GridFragment和ListFragment復用
public abstract class AbsListViewBaseFragment extends BaseFragment {
protected static final String STATE_PAUSE_ON_SCROLL = STATE_PAUSE_ON_SCROLL;
protected static final String STATE_PAUSE_ON_FLING = STATE_PAUSE_ON_FLING;
protected AbsListView listView;
//列表滾動是否暫停加載圖片
protected boolean pauseOnScroll = true;
//列表猛的滾動是否暫停加載圖片
protected boolean pauseOnFling = true;
@Override
public void onResume() {
super.onResume();
applyScrollListener();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem pauseOnScrollItem = menu.findItem(R.id.item_pause_on_scroll);
pauseOnScrollItem.setVisible(true);
pauseOnScrollItem.setChecked(pauseOnScroll);
MenuItem pauseOnFlingItem = menu.findItem(R.id.item_pause_on_fling);
pauseOnFlingItem.setVisible(true);
pauseOnFlingItem.setChecked(pauseOnFling);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_pause_on_scroll:
pauseOnScroll = !pauseOnScroll;
item.setChecked(pauseOnScroll);
applyScrollListener();
return true;
case R.id.item_pause_on_fling:
pauseOnFling = !pauseOnFling;
item.setChecked(pauseOnFling);
applyScrollListener();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
protected void startImagePagerActivity(int position) {
Intent intent = new Intent(getActivity(), SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX);
intent.putExtra(Constants.Extra.IMAGE_POSITION, position);
startActivity(intent);
}
//滾動列表時,是否暫停加載圖片的監聽
//第一個參數就是我們的圖片加載對象ImageLoader, 第二個是控制是否在滑動過程中暫停加載圖片,如果需要暫停傳true就行了,第三個參數控制猛的滑動界面的時候圖片是否加載
private void applyScrollListener() {
listView.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), pauseOnScroll, pauseOnFling));
}
}
ImageListFragment
1,有關於DisplayImageOptions的設置,各情況加載的圖片以及緩存等的設置
在DisplayImageOptions選項中配置bitmapConfig為Bitmap.Config.RGB_565,因為默認是ARGB_8888, 使用RGB_565會比使用ARGB_8888少消耗2倍的內存
2,還有關於漸進動畫的設置AnimateFirstDisplayListener
/*******************************************************************************
* Copyright 2011-2014 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.sample.fragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImageListFragment extends AbsListViewBaseFragment {
public static final int INDEX = 0;
String[] imageUrls = Constants.IMAGES;
DisplayImageOptions options;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.displayer(new RoundedBitmapDisplayer(20))//設置圓角
.build();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_list, container, false);
//listView都是繼承自AbsListViewBaseFragment的listView
listView = (ListView) rootView.findViewById(android.R.id.list);
((ListView) listView).setAdapter(new ImageAdapter());
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
@Override
public void onDestroy() {
super.onDestroy();
AnimateFirstDisplayListener.displayedImages.clear();
}
private static class ViewHolder {
TextView text;
ImageView image;
}
class ImageAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
ImageAdapter() {
inflater = LayoutInflater.from(getActivity());
}
@Override
public int getCount() {
return imageUrls.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.item_list_image, parent, false);
holder = new ViewHolder();
holder.text = (TextView) view.findViewById(R.id.text);
holder.image = (ImageView) view.findViewById(R.id.image);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.text.setText(Item + (position + 1));
ImageLoader.getInstance().displayImage(imageUrls[position], holder.image, options, animateFirstListener);
return view;
}
}
//設圖片第一次加載完成的漸入動畫
//取得加載完成圖片的uri,看是否在已經顯示的圖片列表中,沒有即第一次則顯示加載動畫並加入到顯示列表
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
static final List displayedImages = Collections.synchronizedList(new LinkedList());
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
}
顯示加載進度的監聽SimpleImageLoadingListener
/*******************************************************************************
* Copyright 2011-2014 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.sample.fragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImageGridFragment extends AbsListViewBaseFragment {
public static final int INDEX = 1;
String[] imageUrls = Constants.IMAGES;
DisplayImageOptions options;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_grid, container, false);
listView = (GridView) rootView.findViewById(R.id.grid);
((GridView) listView).setAdapter(new ImageAdapter());
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
public class ImageAdapter extends BaseAdapter {
private LayoutInflater inflater;
ImageAdapter() {
inflater = LayoutInflater.from(getActivity());
}
@Override
public int getCount() {
return imageUrls.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View view = convertView;
if (view == null) {
view = inflater.inflate(R.layout.item_grid_image, parent, false);
holder = new ViewHolder();
assert view != null;
holder.imageView = (ImageView) view.findViewById(R.id.image);
holder.progressBar = (ProgressBar) view.findViewById(R.id.progress);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
//這裡有顯示圖片加載進度的方法
ImageLoader.getInstance()
.displayImage(imageUrls[position], holder.imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
holder.progressBar.setProgress(0);
holder.progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
holder.progressBar.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
holder.progressBar.setVisibility(View.GONE);
}
}, new ImageLoadingProgressListener() {
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
holder.progressBar.setProgress(Math.round(100.0f * current / total));
}
});
return view;
}
}
static class ViewHolder {
ImageView imageView;
ProgressBar progressBar;
}
}
注意在此Fragment中通過getArguments方法取得在SimpleImageActivity中setArguments的position的值,對應正確的條目
/*******************************************************************************
* Copyright 2011-2014 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.sample.fragment;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImagePagerFragment extends BaseFragment {
public static final int INDEX = 2;
String[] imageUrls = Constants.IMAGES;
DisplayImageOptions options;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_pager, container, false);
ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
pager.setAdapter(new ImageAdapter());
//在Fragment中取出傳過來的值getArguments()返回bundle
pager.setCurrentItem(getArguments().getInt(Constants.Extra.IMAGE_POSITION, 0));
return rootView;
}
private class ImageAdapter extends PagerAdapter {
private LayoutInflater inflater;
ImageAdapter() {
inflater = LayoutInflater.from(getActivity());
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return imageUrls.length;
}
@Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false);
assert imageLayout != null;
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
ImageLoader.getInstance().displayImage(imageUrls[position], imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason.getType()) {
case IO_ERROR:
message = Input/Output error;
break;
case DECODING_ERROR:
message = Image can't be decoded;
break;
case NETWORK_DENIED:
message = Downloads are denied;
break;
case OUT_OF_MEMORY:
message = Out Of Memory error;
break;
case UNKNOWN:
message = Unknown error;
break;
}
Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE);
}
});
view.addView(imageLayout, 0);
return imageLayout;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
@Override
public Parcelable saveState() {
return null;
}
}
}
《Android源碼設計模式解析與實戰》讀書筆記(十八)
第十八章、代理模式 代理模式也稱委托模式,是結構型設計模式之一。是應用廣泛的模式之一。1.定義為其他對象提供一種代理以控制對這個對象的訪問。2.使用場景當無法或不想直接訪
Android中使用Bitmap類將矩形圖片轉為圓形的方法
一般要做正圓形圖片,只能是正方形的基礎上才能實現,否則就變成橢圓了,下面說說如何使長方形的圖片生成正圓形圖片廢話不多說,沒圖沒真相,先上圖吧:原圖:變成正圓後:下面上代碼
Android shape和selector 結合使用實例代碼
shape和selector是Android UI設計中經常用到的,比如我們要自定義一個圓角Button,點擊Button有些效果的變化,就要用到shape和select
sd卡壞了怎麼辦 sd卡壞了能修復嗎 sd卡壞了數據恢復
相信不少朋友在平常的學習和工作當中都會用到SD存儲卡,雖然它具有是很強大的存儲功能,但同時也是非常脆弱的。一旦SD卡罷工,真是欲哭無淚。那麼到底sd卡壞了怎