屏幕截圖

Activity界面區(qū)域劃分

如圖:最大的紅色區(qū)域是屏幕界面,綠色次大區(qū)域我們稱之為“應(yīng)用界面區(qū)域”,藍色的區(qū)域我們稱之為“View繪制區(qū)域”;屏幕頂端、應(yīng)用界面區(qū)之外的那部分顯示手機電池網(wǎng)絡(luò)運營商信息的為“狀態(tài)欄”,應(yīng)用區(qū)域頂端、View繪制區(qū)外部顯示Activity名稱的部分我們稱為“標(biāo)題欄”。

獲取狀態(tài)欄高度

獲取狀態(tài)欄一般常用的有三種方法:

  1. 通過系統(tǒng)資源尺寸獲取

    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if(resourceId > 0){
        int statusBarHeight = getResources().getDimensionPixelSize(resourceId);
    }
        
    

使用getIdentifier()方法

方法一
Resources resources = context.getResources();

int resourceId = resources.getIdentifier(com.test.androidtest:drawable/icon",null,null);

第一個參數(shù)格式是:包名 + : + 資源文件夾名 + / +資源名,然后其他的可以為null
#####方法二

Resources resources = context.getResources();
int resourceId = getResources().getIdentifier("icon", "drawable", "com.test.androidtest");

第一個參數(shù)為ID名,第二個為資源屬性是ID或者是Drawable,第三個為包名。

一般來講是推薦第二種方法

在獲取狀態(tài)欄高度時, 因為狀態(tài)欄高度定義在Android系統(tǒng)尺寸資源中status_bar_height,但并不能公開使用,一般會像這樣使用:android.R.dimen.status_bar_height,由于系統(tǒng)為我們提供了一個Resource類,所以我們可以通過這個類來獲取資源 status_bar_height.

因此代碼的寫法是

int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");

可對照getIdentifier()的方法二進行比對

  1. 使用屏幕和應(yīng)用區(qū)域高度的差值確定

      // 獲取狀態(tài)欄高度
     Rect frame = new Rect();
     // 測量屏幕寬和高
     view.getWindowVisibleDisplayFrame(frame);
     int stautsHeight = frame.top;
    

    如果單單獲取statusBar高度而不獲取titleBar高度時,這種方法并不推薦大家使用,因為這種方法依賴于WMS(窗口管理服務(wù)的回調(diào))。正是因為窗口回調(diào)機制,所以在Activity初始化時執(zhí)行此方法得到的高度是0,這就是很多人獲取到statusBar高度為0的原因。這個方法推薦在回調(diào)方法onWindowFocusChanged()中執(zhí)行,才能得到預(yù)期結(jié)果。

  2. 使用應(yīng)用區(qū)域的top屬性

     //屏幕  
     DisplayMetrics dm = new DisplayMetrics();  
     
     getWindowManager().getDefaultDisplay().getMetrics(dm);  
    
     //應(yīng)用區(qū)域  
     Rect outRect1 = new Rect();  
    
     getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);  
    
    int statusBar = dm.heightPixels - outRect1.height();  //狀態(tài)欄高度=屏幕高度-應(yīng)用區(qū)域高度  
    

獲取標(biāo)題欄高度

  1. 通過View提供的方法獲取高度
  int viewTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

通過Activity的getWindow().findViewById(Window.ID_ANDROID_CONTENT)獲取系統(tǒng)當(dāng)前顯示的view根(是一個framelayout對象),android繪制會將要繪制的view放置在framelayout中繪制。

  1. 通過屏幕獲取高度
       int statusHeight = -1;
    //屏幕
       DisplayMetrics dm = new DisplayMetrics();

       activity.getWindowManager().getDefaultDisplay().getMetrics(dm);

       int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");

       if (resourceId > 0) {

           statusHeight = activity.getResources().getDimensionPixelSize(resourceId);

       } 
       //View繪制區(qū)域,//viewtop方法一
       Rect outRect2 = new Rect();
       activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect2);
       int viewTop = dm.heightPixels - statusHeight - outRect2.height();

寫入SD卡

 private static boolean savePic(Bitmap pBitmap, File strName) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(strName);
            if (null != fos) {
                pBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
                fos.flush();
                fos.close();
                return true;
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

關(guān)于flush()方法,api中有如下描述

刷新此輸出流并強制寫出所有緩沖的輸出字節(jié)(刷新數(shù)據(jù)并將數(shù)據(jù)轉(zhuǎn)交給操作系統(tǒng) )

實現(xiàn)截圖

 /**
     * 截圖
     *
     * @param activity
     * @return 截圖并且保存sdcard成功返回true,否則返回false
     */
    public static boolean shotBitmap(Activity activity) {
        String sdCardDir = Environment.getExternalStorageDirectory() + "/jietu/";
        File dirFile = new File(sdCardDir);  //目錄轉(zhuǎn)化成文件夾
        if (!dirFile.exists()) {              //如果不存在,那就建立這個文件夾
            dirFile.mkdirs();
        }
        //指定目錄
        File file = new File(sdCardDir, System.currentTimeMillis() + ".png");
        return ScreenShotUtils.savePic(takeScreenShot(activity), file);
    }

Environment.getExternalStorageDirectory()是獲得根目錄,System.currentTimeMillis()是獲得系統(tǒng)時間

File file = new File(sdCardDir, System.currentTimeMillis() + ".png");

這句話的意思就是,截下來的圖以 ==當(dāng)前系統(tǒng)時間戳.png== 的形式存到根目錄下的 ==jietu== 文件夾下。

終極代碼

MainActivity:

public class MainActivity extends AppCompatActivity {

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

        Button button = (Button) findViewById(R.id.btn);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                boolean result = ScreenShotUtils.shotBitmap(MainActivity.this);
                if (result) {
                    Toast.makeText(MainActivity.this, "截圖成功.", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "截圖失敗.", Toast.LENGTH_SHORT).show();
                }
            }
        });

    }
}

ScreenShotUtils:

/**
 * 進行截屏工具類
 */
public class ScreenShotUtils {
    /**
     * 進行截取屏幕
     *
     * @param activity
     * @return bitmap
     */
    public static Bitmap takeScreenShot(Activity activity) {
        Bitmap bitmap = null;
        int statusHeight = -1;
        View view = activity.getWindow().getDecorView();
        // 設(shè)置是否可以進行繪圖緩存
        view.setDrawingCacheEnabled(true);
        // 如果繪圖緩存無法,強制構(gòu)建繪圖緩存
        view.buildDrawingCache();
        // 返回這個緩存視圖
        bitmap = view.getDrawingCache();
        Log.d("123", "bitmap.getHeight():" + bitmap.getHeight());

        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {

            statusHeight = activity.getResources().getDimensionPixelSize(resourceId);

        }
        int viewTop = activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

        int width = activity.getWindowManager().getDefaultDisplay().getWidth();
        int height = activity.getWindowManager().getDefaultDisplay().getHeight();
        // 根據(jù)坐標(biāo)點和需要的寬和高創(chuàng)建bitmap
        bitmap = Bitmap.createBitmap(bitmap, 0, statusHeight + viewTop, width, height - statusHeight - viewTop);
        return bitmap;
    }


    /**
     * 保存圖片到sdcard中
     *
     * @param pBitmap
     */
    private static boolean savePic(Bitmap pBitmap, File strName) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(strName);
            if (null != fos) {
                pBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
                fos.flush();
                fos.close();
                return true;
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 截圖
     *
     * @param activity
     * @return 截圖并且保存sdcard成功返回true,否則返回false
     */
    public static boolean shotBitmap(Activity activity) {
        String sdCardDir = Environment.getExternalStorageDirectory() + "/wurenji/";
        File dirFile = new File(sdCardDir);  //目錄轉(zhuǎn)化成文件夾
        if (!dirFile.exists()) {              //如果不存在,那就建立這個文件夾
            dirFile.mkdirs();
        }
        //指定目錄
        File file = new File(sdCardDir, System.currentTimeMillis() + ".png");
        return ScreenShotUtils.savePic(takeScreenShot(activity), file);
    }


}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/gray"
    tools:context="com.test.screenshot.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="點擊截圖哦"
        android:gravity="center"
        android:padding="10dp"
        android:textSize="20sp" />

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dip"
        android:scaleType="fitXY" />

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dip"
        android:text="點擊截圖" />

</LinearLayout>

參考博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容