属性动画
- 动画: 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();
}
}
}
}
}