android 画笔和画布的使用,实现类似360清除内存的画面

3 篇文章 0 订阅
1 篇文章 0 订阅

代码上已经写好了注释, 因时间关系只写了关键部分的注释,如有不理解的可以给我留言, 我会帮你解读的。

//UI类

package com.example.atest_rectui.widget;


import java.util.List;

import com.example.atest_rectui.R;
import com.example.atest_rectui.util.Utils;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Handler.Callback;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;


/**
 * @author snake
 * UI类, 直接在xml文件配置 即可使用
 *
 */

public class ClearMemoryView extends TextView implements Callback {
 private static final String TAG = ClearMemoryView.class.getSimpleName();
 
 private static final int REFRESHING  = 0x01;
 private static final int REFRESH_UI = 0x02;
 private static final int REFRESH_END = 0x03;
 private Context mContext = null;
 private Handler mHandler = null;
 /** 画圆的画笔 */
 private Paint mCircularPaint;
 /** 写字体的画笔 */
 private Paint mTxtPaint;
 private RectF mRectF;
 private RectF mRectFrame;
 /** View的宽度 */
 private int mViewWidth = 0;
 /** View的高度 */
 private int mViewHeight = 0;
 /** 圆的宽度 */
 private int mCircularWidth = 0;
 /** 当前的进度 */
 private int mCurrentProgress = 100;
 private int mMax = 100;
 private long mMaxValue = 0;
 private float mSweepAngle;
 private float mTxtSize = 0.0f;
 /** ClearAppsIcon的进度 */
 private int mProgress = 0;
 /** 允许清除apps的标志 */
 private boolean mAllowClear = true;
 /** 之前的内存 */
 private long mBeforeMem = 0l;
 private float mIconPadding = 20;
 
 
 private float paintwidth = 12;
 private Paint mCenterPaint;
 private Paint mPerentPaint;
 
 public ClearMemoryView(Context context) {
  this(context, null);
 }

 public ClearMemoryView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }

 public ClearMemoryView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  mContext = context;
  mHandler = new Handler(this);
  mViewWidth = (int)mContext.getResources().getDimension(R.dimen.dimen_bottom_item_layout);
  mViewHeight = (int)mContext.getResources().getDimension(R.dimen.dimen_bottom_item_layout);
  initData();
  
 }

 private void initData() {
  
  mCircularWidth = (int)(mViewWidth * 0.78f);
  Log.d(TAG, "Clear View Circular==" + mCircularWidth + "::CellWidth==" + mViewWidth + ":::getScrollX() = " + getScrollX());
  mRectF = new RectF();
  mRectFrame = new RectF();
  // 初始化画圆形的画笔
  mCircularPaint = new Paint();
  
  //设置画布填充模式 , Paint.Style.STROKE表示中间区域是 镂空的
  mCircularPaint.setStyle(Paint.Style.STROKE);
  
  //当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的图形样式,如圆形样式   Cap.ROUND,或方形样式Cap.SQUARE  
  mCircularPaint.setStrokeCap(Paint.Cap.ROUND);
  
  //设置绘制时各图形的结合方式,如平滑效果等
  mCircularPaint.setStrokeJoin(Paint.Join.ROUND);
  
  //设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰 
  mCircularPaint.setDither(true);
  
  //设置是否使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢。  
  mCircularPaint.setAntiAlias(true);
  
  //当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度 
  mCircularPaint.setStrokeWidth(paintwidth);
  
  mCenterPaint = new Paint();
  mCenterPaint.setStyle(Paint.Style.FILL);
  mCenterPaint.setDither(true);
  mCenterPaint.setAntiAlias(true);
  mCenterPaint.setColor(Color.parseColor("#eeeeee"));
  // 设置渐变的颜色组,也就是按红、绿、蓝的方式渐变
//  int[] colors = new int[]{Color.parseColor("#00EC00"), Color.parseColor("#00BB00"), Color.parseColor("#009100")};
//  Shader shader = new SweepGradient(getWidth() / 2, 0, colors, null);
//  mCircularPaint.setShader(shader);
  // 初始化写文字的画笔
  mTxtPaint = new Paint();
  mTxtSize = 33;
  
  mTxtPaint.setTextSize(mTxtSize);
  mTxtPaint.setAntiAlias(true);
//  Typeface typeface = Typeface.createFromAsset(mContext.getAssets(), "fonts/segoemcl.ttf");
//  mTxtPaint.setTypeface(typeface);
  mTxtPaint.setColor(Color.BLACK);
  
  mPerentPaint = new Paint();
  mPerentPaint.setTextSize(22);
  mPerentPaint.setAntiAlias(true);
//  mPerentPaint.setTypeface(typeface);
  mPerentPaint.setColor(Color.BLACK);
  // 初始化值
  setMaxValue(Utils.getTotalMemory(mContext));
  setProgressValue(Utils.getUsedMemory(mContext));
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
  // TODO Auto-generated method stub
  super.onDraw(canvas);
  // 圆环
  float fLeft = mViewWidth - mCircularWidth;
//  float fTop = (mViewHeight - mCircularWidth) / 2 + mIconPadding;
  float fTop = (mViewHeight - mCircularWidth);
  mRectFrame.set(getScrollX() + fLeft-8, fTop-8, getScrollX() + mCircularWidth+8 , mCircularWidth+8);
  mCircularPaint.setStrokeWidth(8);
  mCircularPaint.setColor(Color.parseColor("#32f9f9f9"));
//  mCircularPaint.setColor(Color.parseColor("#00ff00"));
  canvas.drawArc(mRectFrame, 275, 360, false, mCircularPaint);
  
  
  mRectF.set(getScrollX() + fLeft, fTop, getScrollX() + mCircularWidth, mCircularWidth);
  
  
  mCircularPaint.setStrokeWidth(paintwidth);
  mCircularPaint.setColor(Color.parseColor("#757575"));
  canvas.drawArc(mRectF, 275, 360, false, mCircularPaint);
  mSweepAngle = ((float)mCurrentProgress / mMax )*360;
  if(mSweepAngle >= 324) {
   // 90% 324
//   mCircularPaint.setColor(Color.RED);
   mCircularPaint.setColor(Color.parseColor("#91c7c1"));
   
  } else if(mSweepAngle >= 216) {
   // 60% 216
//   mCircularPaint.setColor(Color.parseColor("#ed610a"));
   mCircularPaint.setColor(Color.parseColor("#91c7c1"));
   
  } else {
//   mCircularPaint.setColor(Color.GREEN);
   mCircularPaint.setColor(Color.parseColor("#91c7c1"));
  }
  canvas.drawArc(mRectF, 275, mSweepAngle, false, mCircularPaint);
  
  
  mRectF.set(getScrollX() + fLeft+6, fTop+5, getScrollX() + mCircularWidth -5, mCircularWidth-5);
  canvas.drawArc(mRectF, 275, 360, false, mCenterPaint);
  
  
  // 文字内容
  long nPercentage = mCurrentProgress * 100 / mMax;
//  String strPercentage = String.format("%d%%", nPercentage);
  String strPercentage = String.valueOf(nPercentage);
  String percentage = "%";
  // 文字的长度
  float fTxtLeght = mTxtPaint.measureText(strPercentage);
  float fPercentLenght = mPerentPaint.measureText("%");
  float fTxtHeight = mTxtPaint.measureText("+");
  float nLeft = (mViewWidth - fTxtLeght) / 2;
  
  float nTop = (mCircularWidth + fTxtHeight) / 2 + mIconPadding;
//  float nTop = (mViewWidth - fTxtHeight) / 2;
  
  mTxtPaint.setTextSize(33);
  canvas.drawText(strPercentage, getScrollX() + nLeft - fPercentLenght/2, nTop, mTxtPaint);
  canvas.drawText(percentage, getScrollX() + nLeft + fTxtLeght*3/4 , nTop, mPerentPaint);
 }
 
 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  // TODO Auto-generated method stub
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  setMeasuredDimension(mViewWidth, mViewHeight);
 }
 
 /**
  * 获取比例值
  * @return
  */
 public int getProgress() {
  return mCurrentProgress;
 }
 
 /**
  * 当前的比例
  * @param progress
  */
 public void setProgressValue(long progress) {
  if(progress < 0) {
   progress = 0;
  }
  if(progress > mMaxValue) {
   progress = mMaxValue;
  }
  mCurrentProgress = (int)(progress * 100 / mMaxValue);
  invalidate();
 }
 
 public void setProgress(int progress) {
  if(progress < 0) {
   progress = 0;
  }
  if(progress > mMax) {
   progress = mMax;
  }
  mCurrentProgress = progress;
  invalidate();
 }

 /**
  * 定义的最大值
  * @param max
  */
 public void setMax(int max) {
  mMax = max;
 }
 
 public int getMax() {
  return mMax;
 }
 
 /**
  *
  */
 public void setMaxValue(long maxValue) {
  mMaxValue = maxValue;
 }
 
 /**
  * 清除Apps,释放内存
  */
 private void clearApps() {
  
  ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> infoList = am.getRunningAppProcesses();
//        List<ActivityManager.RunningServiceInfo> serviceInfos = am.getRunningServices(100);
        mBeforeMem = Utils.getAvailMemory(mContext);
        if (infoList != null) {
            for (int i = 0; i < infoList.size(); ++i) {
                RunningAppProcessInfo appProcessInfo = infoList.get(i);
//                Log.d(TAG, "process name : " + appProcessInfo.processName);
                //importance 该进程的重要程度  分为几个级别,数值越低就越重要。
                Log.d(TAG, "importance : " + appProcessInfo.importance);

                // 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE的进程都长时间没用或者空进程了
                // 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE的进程都是非可见进程,也就是在后台运行着
                if (appProcessInfo.importance > RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                    String[] pkgList = appProcessInfo.pkgList;
                    for (int j = 0; j < pkgList.length; ++j) {//pkgList 得到该进程下运行的包名
                        if("com.sen5.launcher".equals(pkgList[j]) || "com.amlogic.DVBPlayer".equals(pkgList[j])) {
                         continue;
                        }
                        try {
                         am.killBackgroundProcesses(pkgList[j]);
                        } catch(SecurityException e) {
                         Log.e(TAG, "killBackgroundProcesses error==" + e.toString());
                        }
                    }
                }
            }
        }
 }
 
 /**
  * 更新界面的动画
  */
 private void refeshUI() {
  
  new Thread(new Runnable() {
   
   @Override
   public void run() {
    
    for(; mProgress > -1; mProgress--) {
     
     mHandler.sendEmptyMessage(REFRESH_UI);
     try {
      Thread.sleep(20);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    int nUsedMemory = (int)(Utils.getUsedMemory(mContext) * getMax()
      / Utils.getTotalMemory(mContext));
    for(; mProgress <= nUsedMemory; mProgress++) {
     
     mHandler.sendEmptyMessage(REFRESH_UI);
     try {
      Thread.sleep(20);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     nUsedMemory = (int)(Utils.getUsedMemory(mContext) * getMax()
       / Utils.getTotalMemory(mContext));
    }
    mHandler.sendEmptyMessage(REFRESH_END);
   }
  }).start();
  
 }
 
 /**
  * 开始清除内存
  */
 public void startClearApps() {
  
  if(!mAllowClear) {
   return;
  }
  mProgress = getProgress();
  new Thread(new Runnable() {
   
   @Override
   public void run() {
    // TODO Auto-generated method stub
    mAllowClear = false;
    mHandler.sendEmptyMessage(REFRESHING);
    clearApps();
   }
  }).start();
  
 }
 
 /**
  * 刷新内存的现实,一般在应用打开时就得调用
  */
 public void refreshIconValue() {
  
  setProgressValue(Utils.getUsedMemory(mContext));
 }
 
 @Override
 public boolean handleMessage(Message msg) {
  // TODO Auto-generated method stub
  switch(msg.what) {
  case REFRESHING:
   refeshUI();
   break;
   
  case REFRESH_UI:
   setProgress(mProgress);
   break;
   
  case REFRESH_END:
   mAllowClear = true;
   // 清除内存的结果显示
   long currentMem = Utils.getAvailMemory(mContext);
   Log.d(TAG, "AvailMem===" + currentMem + ":::BeforeMem===" + mBeforeMem);
   String strHint = "";
   if(currentMem > mBeforeMem) {
    String strReleaseMem = mContext.getString(R.string.release_memory);
    String strCurrentMem = mContext.getString(R.string.currunt_memory);
    strHint = String.format("%s %dM,\n%s %dM", strReleaseMem, (currentMem - mBeforeMem)
      , strCurrentMem, currentMem);
   } else {
    strHint = mContext.getString(R.string.best_memory_status);
   }
   
   Toast.makeText(mContext, strHint, Toast.LENGTH_SHORT).show();
   
   break;
   
  default:
   break;
  }
  
  return false;
 }
}


//以下是Main调用类

package com.example.atest_rectui;

import com.example.atest_rectui.widget.ClearMemoryView;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

/**
 * @author snake
 * 调用类
 */
public class MainActivity extends Activity implements OnClickListener{

 private ClearMemoryView mClearMemoryView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  initView();
 }

 private void initView() {
  mClearMemoryView = (ClearMemoryView)findViewById(R.id.tv_myclearmemory);
  mClearMemoryView.setOnClickListener(this);
  mClearMemoryView.refreshIconValue();
 }

 @Override
 public void onClick(View v) {
  // TODO Auto-generated method stub
  switch (v.getId()) {
  case R.id.tv_myclearmemory:
   mClearMemoryView.startClearApps();
   break;

  default:
   break;
  }
 }
}

//以下是工具类

package com.example.atest_rectui.util;

import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;

/**
 * @author snake
 * 工具类
 */
public class Utils {
 
 /**
  * 获取可用内存大小
  * @param context
  * @return
  */
    public static long getAvailMemory(Context context) {
       
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        MemoryInfo mi = new MemoryInfo();
        am.getMemoryInfo(mi);
        //return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化
        return mi.availMem / (1024 * 1024);
    }
   
    /**
  * 获取已用内存大小
  * @param context
  * @return
  */
    public static long getUsedMemory(Context context) {
       
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        MemoryInfo mi = new MemoryInfo();
        am.getMemoryInfo(mi);
        //return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化
        return (mi.totalMem - mi.availMem) / (1024 * 1024);
    }
   
    /**
  * 获取总的内存大小
  * @param context
  * @return
  */
    public static long getTotalMemory(Context context) {
       
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        MemoryInfo mi = new MemoryInfo();
        am.getMemoryInfo(mi);
        return mi.totalMem / (1024 * 1024);
    }

}


//资源文件

activity_main.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.atest_rectui.MainActivity" >

    <com.example.atest_rectui.widget.ClearMemoryView
        android:id="@+id/tv_myclearmemory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:focusable="true"
         />

</RelativeLayout>


dimens.xml 文件

<resources>

    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
 <dimen name="dimen_bottom_item_layout">110dp</dimen>
</resources>


strings.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">atest_rectui</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="release_memory">Release memory for</string>
    <string name="currunt_memory">Current memory available is</string>
    <string name="best_memory_status">Has been cleaned up to the best</string>
</resources>








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值