屬性動畫
- 動畫: UI漸變, 變量值的變化
- ObjectAnimator : ofInt(“backgroundColor”,start,end);
ValueAnimator:
for(int i = start; i< end; i++) { a = i; }
ValueAnimator animation=ValueAnimator.ofInt(start,end); animation.setDuration(DURATION); animation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int animationValue=(Integer) animation.getAnimatedValue(); mHeaderlayout.setPadding(0, animationValue, 0, 0); }
});
animation.start();
刷新頁面是使用ValueAnimator場景之一,以提高用戶體驗性。addUpdateListener這個方法不斷更新高度,使其漸變收縮。從一開始的start到end。其他地方法就不介紹了,想了解的就去看看源碼吧。
ListView頁面數據點擊已讀的設置
實現條目點擊的事件,把點擊條目的唯一標識符id存儲起來,通知listview適配器更新。
listviewAdapter.notifyDataSetChanged();
在listview適配器中的getView()方法中判斷當前position的id是否在存儲的數據中(自定義區分的規則),若存在,設置文本字體爲灰色,不存在則爲黑色。
//設置已讀爲灰色
String itemId="#"+bean.id+"#";
String readIds=GetDataShared.getString(mContext, KEY_READ_LIST);
boolean isRead=!TextUtils.isEmpty(readIds)&& readIds.contains(itemId);
holder.textlist.setTextColor(isRead ? Color.GRAY:Color.BLACK);
頁面中webView的使用
WebView listWeb=(WebView) findViewById(R.id.news_detial_wv);
//根據url去加載數據
listWeb.loadUrl(url);
//設置webview參數
WebSettings setting=listWeb.getSettings();//獲取webview的設置
//默認爲false,不支持javascrip,設置爲true可收縮
setting.setJavaScriptEnabled(true);//設置js可用
setting.setBuiltInZoomControls(true); //設置放大和縮小可見
setting.setUseWideViewPort(true);//設置手勢雙擊放大或縮小
改變webview中參數的大小:定義一個方法:mCurrentheckedItem爲存儲的值(0-4),要想做緩存就把mCurrentheckedItem的值存儲起來,在每次初始化的時候先判斷存儲的值是否存在且不爲空。
private void initTextSize()
{
TextSize ts =null;
switch(mCurrentheckedItem){
case 0:
ts=TextSize.LARGEST;
break;
case 1:
ts=TextSize.LARGER;
break;
case 2:
ts=TextSize.NORMAL;
break;
case 3:
ts=TextSize.SMALLER;
break;
case 4:
ts=TextSize.SMALLEST;
break;
}
listWeb.getSettings().setTextSize(ts);
}
設置監聽常用的兩個API,第一個無法滿足需求就可以使用第二個。
//設置監聽1,進度條的顯示切換在這裏監聽
listWeb.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url)
{
//數據加載完成時調用,隱藏進度條
listPb.setVisibility(View.GONE);
}
});
//監聽2,進度條的更新要在這個api裏監聽
listWeb.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress)
{
//更新進度條
Log.i(TAG, newProgress+"");
}
});
自定義加載時環形進度條
把一個xml文件嵌套進進度條中:環形正向和反向同時轉然後匯聚再分開,循環
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<rotate
android:fromDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="990" >
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="20dp"
android:shape="ring"
android:thickness="5dp"
android:useLevel="false" >
<gradient
android:endColor="#88ffffff"
android:startColor="#88ff0000"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
</item>
<item>
<rotate
android:fromDegrees="990"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="-90" >
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="20dp"
android:shape="ring"
android:thickness="5dp"
android:useLevel="false" >
<gradient
android:endColor="#88ffffff"
android:startColor="#88ff0000"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
</item>
</layer-list>
在Probress中設置應用:設置屬性indeterminateDrawable,在這裏引用佈局
<ProgressBar
android:id="@+id/news_detial_pb"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/loadingpb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
一鍵分享,使用第三方分享SDK,現在有大量的平臺提供分享,這裏以Mob爲例說明一下使用的方法。
1、首先在mob官網註冊一個賬號。創建應用, 獲取ShareSDK的AppKey
2、 下載SDK,點擊下載之後如下圖所以,點擊下載SDK的下載頁,展開平臺可以選擇其他的第三方平臺;demo也是這裏下載;
3、 快速集成(具體參考mob官方Android集成文檔)、
(1)、使用快速工具進行集成
(2)、配置AndroidManifest.xml 添加權限、添加activity信息、替換mob後臺申請的Appkey與各個平臺申請的key
4、添加分享代碼
private void showShare() {
ShareSDK.initSDK(this);
OnekeyShare oks = new OnekeyShare();
//關閉sso授權
oks.disableSSOWhenAuthorize();
// 分享時Notification的圖標和文字 2.5.9以後的版本不調用此方法
//oks.setNotification(R.drawable.ic_launcher, getString(R.string.app_name));
// title標題,印象筆記、郵箱、信息、微信、人人網和QQ空間使用
oks.setTitle(getString(R.string.share));
// titleUrl是標題的網絡鏈接,僅在人人網和QQ空間使用
oks.setTitleUrl("http://sharesdk.cn");
// text是分享文本,所有平臺都需要這個字段
oks.setText("我是分享文本");
// imagePath是圖片的本地路徑,Linked-In以外的平臺都支持此參數
//oks.setImagePath("/sdcard/test.jpg");//確保SDcard下面存在此張圖片
// url僅在微信(包括好友和朋友圈)中使用
oks.setUrl("http://sharesdk.cn");
// comment是我對這條分享的評論,僅在人人網和QQ空間使用
oks.setComment("我是測試評論文本");
// site是分享此內容的網站名稱,僅在QQ空間使用
oks.setSite(getString(R.string.app_name));
// siteUrl是分享此內容的網站地址,僅在QQ空間使用
oks.setSiteUrl("http://sharesdk.cn");
// 啓動分享GUI
oks.show(this);
}
這裏就可以使用分享東西到多社交平臺了。
ShareSDK集成的主要步驟
- 註冊賬號
- 創建應用
- 下載sdk
- SDK 導入配置
- 代碼配置
圖片的三級緩存## 圖片的三級緩存
引用
- 強引用: 應用程序崩潰時都不會回收,成員變量
- 軟引用: 當應用程序內存不足的時候,系統會回收(JVM) SoftReference
- 弱引用:當jvm的回收機制運行時,就回收
- 虛引用:應用場景很少
3.0: bitmap緩存時,用軟引用
- LruCache: Lru less recently use
首先是頁面要顯示圖片,到內存中取圖片數據,發現內存中沒有,之後到本地中查詢,有數據就存到內存中,頁面從內存中取出數據顯示;若本地也沒有數據,就到網絡取數據,取出數據就存到本地中,再存到內存中,最後顯示出來。這就是三級緩存的大概步驟。下面來看看圖片流程:
下面就來看看代碼如何實現這些步驟
package com.cca.zhihui.utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
/**
*
* @包名:com.cca.zhihui.utils
* @類名:CacheHelper
* @時間:下午11:07:15
* @author Administrator
*
* @描述:三級緩存的實現原理
*/
public class ImageHelper
{
public static LruCache<String, Bitmap> mCaches = null;
// private Map<String ,SoftReference<Bitmap>>
private static String mCacheDir; //系統緩存目錄
private static Handler mHandler; //handler機制
private ExecutorService mPool; //線程管理者
private static Map<ImageView,Future<?>> mFuture;
public ImageHelper(Context context) {
if (mCaches == null)
{
// lru最大佔用的應用的內存
int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);
mCaches = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value)
{
return value.getByteCount();
// 低版本:value.getRowBytes() * value.getHeight()
}
};
}
mCacheDir = getCacheDir(context);
if(mHandler==null){
mHandler=new ImagHandler();
}
//線程管理
if(mPool==null){
mPool=Executors.newFixedThreadPool(3);//只允許開3個子線程
}
if(mFuture==null){
mFuture=new LinkedHashMap<ImageView, Future<?>>();//需要連續的內存地址
}
}
//方法圖片顯示
public void display(ImageView view, String url)
{
// 1、到內存中取數據
Bitmap bitmap = mCaches.get(url);
if (bitmap != null)
{
// 內存中有數據
view.setImageBitmap(bitmap);
return;
}
// 內存中沒有數據
// 2、到本地中取數據
bitmap = getBitmapFromLocal(url);
if (bitmap != null)
{
// 本地中有數據
view.setImageBitmap(bitmap);
return;
}
// 本地也沒有數據
getBitmapFromNet(view, url);
}
private void getBitmapFromNet(ImageView view, String url)
{
// 去網絡獲取數據
//new Thread(new ImageRequestTask(view, url)).start();
//判斷是否有已經在執行的
Future<?> future=mFuture.get(view);
if(future!=null && future.isDone() && !future.isCancelled()){
//正在執行
future.cancel(true);
future=null;
}
future=mPool.submit(new ImageRequestTask(view, url));
mFuture.put(view, future);
}
//從本地獲取圖片資源
private Bitmap getBitmapFromLocal(String url)
{
// 首先找到文件
String name;
try
{
name = MD5Encoder.encode(url);
File file = new File(mCacheDir, url);//mCacheDir、緩存目錄
if (file.exists())
{
// 解析文件爲bitmap
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
// 存到內存中
mCaches.put(url, bitmap);
return bitmap;
}
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
//獲取兩種存儲緩存的目錄
private String getCacheDir(Context context)
{
// 如果有sdcard就用Android/data/appname
if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState())
{
// 有sd卡
File sdDir = Environment.getExternalStorageDirectory();
File dir = new File(sdDir, "/Android/data/" + context.getPackageName() + "/bitmap/");
if (!dir.exists())
{
dir.mkdirs();
}
return dir.getAbsolutePath();
}
else
{
return context.getCacheDir().getAbsolutePath();
}
}
//異步加載圖片數據
class ImageRequestTask implements Runnable
{
private String url;
private ImageView view;
public ImageRequestTask(ImageView iv, String url) {
this.url = url;
this.view = iv;
}
@Override
public void run()
{
try
{
// 去網絡獲取數據
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(5000);// 連接超時
conn.setReadTimeout(5000);// 讀取超時
conn.connect();// 開啓連接
int code = conn.getResponseCode();
if (code == 200)
{
// 訪問網絡成功
// 獲取流,將流解析成bitmap
InputStream in = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(in);
// 存到本地
writeLocal(bitmap, url);
// 存到內存
mCaches.put(url, bitmap);
//主線程中刷新圖片
Message msg=Message.obtain();
msg.obj=new Object[]{view,url};
mHandler.sendMessage(msg);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
class ImagHandler extends Handler{
@Override
public void handleMessage(Message msg)
{
Object[] objs=(Object[]) msg.obj;
ImageView view=(ImageView) objs[0];
String url=(String) objs[1];
//設置UI顯示
display(view, url);
}
}
//把圖片數據寫進本地
public void writeLocal(Bitmap bitmap, String url)
{
String name;
FileOutputStream fos=null;
try
{
name = MD5Encoder.encode(url);
File file = new File(mCacheDir, name);
fos = new FileOutputStream(file);
//壓縮圖片寫進本地,jpeg格式,質量爲100
bitmap.compress(CompressFormat.JPEG, 100, fos);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (fos != null){
try
{
fos.close();
fos=null;
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
}