Создание скриншота определенного макета в Android

У меня есть два основных вопроса, которые тесно связаны между собой. Я смотрю на эти проблемы с программной точки зрения.

(1) — я хочу сделать скриншот содержимого КОНКРЕТНОГО макета, т. е. ScrollView, вложенного в LinearLayout.

(2) - Поскольку ScrollView имеет содержимое, которое выходит за пределы экрана (поэтому возможна прокрутка), как я могу убедиться, что на скриншоте есть элементы, которые не видны на экране?

Это текущий блок кода, который я использую. Он делает снимок экрана, но только для всего экрана. Даже несмотря на то, что R.id.boss является идентификатором ScrollView, а не основного LinearLayout.

View view = findViewById(R.id.boss);
View v = view.getRootView();// this does not seem to make a difference
v.setDrawingCacheEnabled(true);                                                
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());    
v.buildDrawingCache(true);
Bitmap b = Bitmap.createBitmap(u.getDrawingCache());             
v.setDrawingCacheEnabled(false);

Заранее спасибо.

ИЗМЕНИТЬ:

Я сделал несколько ошибок. Я использовал R.id.boss, что является неправильным ресурсом. Теперь я могу сделать снимок экрана только с прокруткой, за исключением частей вне экрана.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/boss"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top"
android:orientation="vertical" >

    <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="F"
    android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Analyze via image URL"
        android:textAppearance="?android:attr/textAppearanceSmall" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
             >

                        <EditText
                            android:id="@+id/mUrl"
                            android:layout_width="fill_parent"
                            android:layout_height="wrap_content"
                            android:layout_weight="0.7"
                            android:text="http://" >

                            <requestFocus />
                        </EditText>

                        <ImageView
                            android:id="@+id/call"
                            android:layout_width="75dp"
                            android:layout_height="50dp"
                            android:layout_weight="0.3"
                            android:text="ABC"
                            android:src="@drawable/run" />

        </LinearLayout>

     <TextView
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="ABC"
         android:textAppearance="?android:attr/textAppearanceSmall" />

     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="wrap_content" >

         <EditText
             android:id="@+id/filepath"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_weight="0.55" />

         <ImageView
             android:id="@+id/cam"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/cam" />

         <ImageView
             android:id="@+id/browse"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/folder"
             android:text="B" />

         <ImageView
             android:id="@+id/upload"
             android:layout_width="75dp"
             android:layout_height="50dp"
             android:layout_weight="0.15"
             android:src="@drawable/run"
             android:text="A" />
     </LinearLayout>


     <LinearLayout
         android:id="@+id/baba"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical" >


         <ScrollView
             android:id="@+id/scroll"
             android:layout_width="fill_parent"
             android:layout_height="150dp"
             android:layout_weight="0.7" >

             <LinearLayout
                 android:layout_width="fill_parent"
                 android:layout_height="186dp"
                 android:orientation="vertical" >

                 <ImageView
                     android:id="@+id/pic"
                     android:layout_width="fill_parent"
                     android:layout_height="fill_parent"
                     android:layout_weight="1" />

                 <TextView
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Facial recognition"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text3"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/avmarwe"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Gender and age"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text1"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/skahasd"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Expression and mood"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text2"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />

                 <TextView
                     android:id="@+id/dsfsfs"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Celebrity Facial Match"
                     android:textAppearance="?android:attr/textAppearanceMedium" />

                 <TextView
                     android:id="@+id/text4"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_weight="1"
                     android:text="Small Text"
                     android:textAppearance="?android:attr/textAppearanceSmall" />
             </LinearLayout>
         </ScrollView>

     </LinearLayout>


    <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" >

        <Button
            android:id="@+id/c"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_weight="0.7"
            android:text="" />

        <Button
            android:id="@+id/share"
            android:layout_width="70dp"
            android:layout_height="50dp"
            android:layout_weight="0.3"
            android:text="" />

    </LinearLayout>

</LinearLayout>

person Reuben L.    schedule 18.05.2012    source источник
comment
Проверьте это - stackoverflow.com/questions/4538429/ - stackoverflow.com/questions/5604125/ - stackoverflow.com/questions/9782595/   -  person silwar    schedule 18.05.2012
comment
см. мой вопрос в разделе EDIT: окончательный результат. .. речь идет о скриншоте закадровой страницы.. Но та же логика работает везде..   -  person Krishnabhadra    schedule 18.05.2012
comment
привет silwar, спасибо, я посмотрел на них. ссылка на 2 действия кажется наиболее близкой к тому, что мне нужно, но я не хочу создавать второе действие.   -  person Reuben L.    schedule 18.05.2012
comment
привет, потому что я не хочу, чтобы весь LinearLayout сохранялся. Просто содержимое ScrollView.   -  person Reuben L.    schedule 18.05.2012
comment
Используя LinearLayout, просто получите его скриншоты, если он содержит все ваши макеты, даже не видимые на экране. Тогда иди дальше.   -  person user370305    schedule 18.05.2012
comment
к сожалению, это не так. он сохраняет только то, что видно на экране.   -  person Reuben L.    schedule 18.05.2012
comment
@Krishnabhadra, могу ли я получить действие B как клон текущего действия, но только с прокруткой?   -  person Reuben L.    schedule 18.05.2012
comment
Также я нашел некоторые ошибки в вашем коде, на u, v..   -  person user370305    schedule 18.05.2012
comment
ааа, так много ошибок в моем коде!! еще я понял, что R.id.boss - неправильный ресурс! На самом деле это основной LinearLayout.   -  person Reuben L.    schedule 18.05.2012
comment
Можете ли вы опубликовать свой файл макета, для которого вы хотите сделать скриншот?   -  person user370305    schedule 18.05.2012
comment
На самом деле, я попробовал код, и он сделал снимок экрана со всеми представлениями от родителя, независимо от того, видны они на экране или нет. Вам не нужно прокручивать.   -  person user370305    schedule 18.05.2012
comment
хм, мой вид прокрутки составляет около 2 экранов в высоту, и я все еще могу сделать снимок экрана только с видимыми частями   -  person Reuben L.    schedule 18.05.2012
comment
Я пробовал с длинным scrollView, только половина которого видна с тем же кодом, но на моем изображении я получил полную компоновку экрана, а также невидимые виды.   -  person user370305    schedule 18.05.2012
comment
давайте продолжим это обсуждение в чате   -  person Reuben L.    schedule 18.05.2012
comment
Также какова структура вашего макета? Scrollview имеет только один дочерний макет?   -  person user370305    schedule 18.05.2012


Ответы (6)


Благодаря вам, ребята, я наконец узнал, что было не так.

View v = view.getRootView(); не следует использовать, потому что это вызовет корневое представление, которое мне не нужно. Я ошибочно подумал, что это не имеет значения, потому что я ввел неправильный идентификатор ресурса.

MeasureSpec как-то не рассчитал ширину и высоту. Поэтому я использовал другой метод:

...
ScrollView z = (ScrollView) findViewById(R.id.scroll);
int totalHeight = z.getChildAt(0).getHeight();
int totalWidth = z.getChildAt(0).getWidth();
u.layout(0, 0, totalWidth, totalHeight);
...

Поскольку общая высота ScrollView может быть определена единственным дочерним элементом, который у него есть.

После внесения этих изменений я теперь могу сделать снимок экрана вложенного ScrollView и всего его содержимого, видимого или нет. Кому интересно, вот блок кода, включая сохранение растрового изображения:

            View u = findViewById(R.id.scroll);
            u.setDrawingCacheEnabled(true);                                                
            ScrollView z = (ScrollView) findViewById(R.id.scroll);
            int totalHeight = z.getChildAt(0).getHeight();
            int totalWidth = z.getChildAt(0).getWidth();
            u.layout(0, 0, totalWidth, totalHeight);    
            u.buildDrawingCache(true);
            Bitmap b = Bitmap.createBitmap(u.getDrawingCache());             
            u.setDrawingCacheEnabled(false);

            //Save bitmap
            String extr = Environment.getExternalStorageDirectory().toString() +   File.separator + "Folder";
            String fileName = new SimpleDateFormat("yyyyMMddhhmm'_report.jpg'").format(new Date());
            File myPath = new File(extr, fileName);
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(myPath);
                b.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.flush();
                fos.close();
                MediaStore.Images.Media.insertImage(getContentResolver(), b, "Screen", "screen");
            }catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
person Reuben L.    schedule 18.05.2012
comment
Извините, могу я спросить, действительно ли эти коды вам помогают? Я сталкиваюсь с теми же проблемами, что и ваш вопрос, но когда я пробую ваш код, он не отображает вид, который я хочу, только черный экран. - person Menma; 29.08.2014
comment
Да, код работал хорошо, и приложение было опубликовано 2 года назад. Вы соответствующим образом настроили переменные? - person Reuben L.; 30.08.2014
comment
ooppss не видел этот код `View u = findViewById(R.id.scroll);` большое спасибо.... - person Menma; 01.09.2014
comment
можно получить снимок экрана gridview, я пробовал код, он принимает всю высоту и ширину gridview, но не содержимое (iamge), он отображает черные ящики - person Hiren Dabhi; 03.10.2014
comment
Это работает, однако мне нужно было сбросить ширину и высоту ScrollView после создания снимка экрана. u.layout(0, 0, totalWidth, totalHeight); код изменяет размеры. - person Eren Yilmaz; 09.10.2014
comment
Я получаю сообщение об ошибке. Просмотр слишком велик, чтобы поместиться в кеш чертежей, требуется 5258880 байт, доступно только 3686400. Тем не менее я не нашел решения, поэтому, пожалуйста, помогите мне. - person Girish Patel; 29.01.2015

попробуй так у меня работает

TableLayout tabLayout = (TableLayout) findViewById(R.id.allview);
if (tabLayout != null) {
    Bitmap image = Bitmap.createBitmap(tabLayout.getWidth(),
            tabLayout.getHeight(), Config.ARGB_8888);
    Canvas b = new Canvas(image);
    tabLayout.draw(b);
}
person Mahtab    schedule 18.06.2014

РЕДАКТИРОВАТЬ: после просмотра комментария OP

Вам вообще не нужно думать о новых действиях. Скажем, вы находитесь в действии прямо сейчас. Макет A — это основной макет для действия, макет B и C — два дочерних макета внутри макета A. Вот так:

 Layout A -> Parent
 |
  -------Layout B
 |
  -------Layout C

Теперь, если вы хотите сделать скриншот только C

1) в onCreate() активности

 LinearLayout myCLayout = (LinearLayout)this.findViewbyId(R.id.my_c_layout);
 ViewTreeObserver vto   =  myCLayout.getViewTreeObserver();
 vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
      //fully drawn, no need of listener anymore
      myCLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      getDrawingBitmap();
   }
 });

где getDrawingBitmap() — это функция, которая делает снимок экрана.

public void getDrawingBitmap(){
    LinearLayout myCLayout = (LinearLayout)this.findViewbyId(R.id.my_c_layout);
    Bitmap b = myCLayout.getDrawingCache();

    File file = saveBitmapAsFile(b);
}

EDIT: для ScrollView

Я никогда не пробовал.. Но я думаю, что вы можете сделать это..

1) сначала переопределите scrollView и переопределите функцию onMeasure.

public class MyScrollView extends ScrollView{
    public MyScrollView(Context context, AttributeSet attrs) {
         super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, yourFullScrollViewHeight));
    }
}

и используйте MyScrollView в своем макете.. здесь yourFullScrollViewHeight - это высота всего содержимого scrollView, для которого вам нужно сделать снимок экрана.. Я никогда не пробовал это.. Но это может сработать..

person Krishnabhadra    schedule 18.05.2012
comment
Я все еще не могу получить полное изображение всего прокрутки с помощью этого метода. Я предполагаю, что это немного отличается от обычной проблемы вне экрана, поскольку содержимое прокрутки, которое не видно, считается вне экрана. - person Reuben L.; 18.05.2012
comment
Пожалуйста, посмотрите мое редактирование.. Я не могу гарантировать, сработает это или нет.. Но на вашем месте я попробую.. - person Krishnabhadra; 18.05.2012
comment
Извините, что вы разместили свой xml после того, как я поставил ответ. Вместо этого вам может потребоваться переопределить LinearLayout внутри scrollView, точно так же, как я переопределяю scrollView в своем ответе.. Переопределите onMeasure и верните полную высоту содержимого. Затем, когда вы сделаете снимок экрана , сделайте скриншот линейного макета (тот, что внутри scrollView) вместо scrollView.. Я думаю, это сработает.. - person Krishnabhadra; 18.05.2012
comment
Хотя я решил это другим способом, я думаю, что вы можете быть правы. Спасибо за помощь! - person Reuben L.; 18.05.2012
comment
@РубенЛ. Я хочу захватить экран RelativeLayout с двумя дочерними представлениями ImageView и TextView, TextView можно перемещать, я пробовал код, но не получаю растровое изображение, так как оно не отображается после вызова другого изображения. - person Abdul Wahab; 11.12.2012

Вот точное решение, которое вам нужно. Оно будет отображать весь экран, включая содержимое, скрытое в вашем ScrollView.

LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
FrameLayout root = (FrameLayout) inflater.inflate(R.layout.activity_main, null); // activity_main is UI(xml) file we used in our Activity class. FrameLayout is root view of my UI(xml) file.
root.setDrawingCacheEnabled(true);
Bitmap bitmap = getBitmapFromView(this.getWindow().findViewById(R.id.frameLayout)); // here give id of our root layout (here its my FrameLayout's id)

Отобразите bitmap в своем ImageView или используйте его по своему усмотрению.
Наслаждайтесь..

person Nirav Dangi    schedule 23.05.2013

У меня также была эта проблема, и я закодировал ее сам.

Я использовал этот код, чтобы сделать скриншот всего макета.

Я изменил размер списка и некоторые математические элементы.

См. следующий веб-сайт,

person muruganvel    schedule 15.10.2012

Попробуйте этот код

общедоступный растровый снимок экрана (просмотр) {

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
    view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    return bitmap;
}
person Thilina Anuradh    schedule 25.05.2015