Сделайте снимок экрана HorizontalScrollView, включая элементы за пределами экрана.

Я пробовал много методов. Я могу сделать снимок экрана всего экрана, НО мое требование - сделать снимок экрана всего HorizontalScrollView и сохранить его как файл изображения. Вот пример макета 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" >

    <HorizontalScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/hsv" >

        <LinearLayout 
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/ll">

             <Button 
                android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:onClick="click"
            android:id="@+id/b"
            android:text="capture"
            android:layout_margin="20dp"/> 

            <ImageView 
                android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:id="@+id/img1"
            android:src="@drawable/plug1"
            android:layout_margin="20dp"/>

            <ImageView 
                android:layout_height="wrap_content"
            android:layout_width="200dp"
            android:id="@+id/img2"
            android:src="@drawable/plug3"
            android:layout_margin="20dp"/>

        </LinearLayout>

    </HorizontalScrollView>

</RelativeLayout>

Код активности:

Button b; 
    ImageView img1, img2; 
    LinearLayout ll; View v; 
    HorizontalScrollView s; 
    int h,w;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        b = (Button)findViewById(R.id.b);
        img1 = (ImageView)findViewById(R.id.img1);
        img2 = (ImageView)findViewById(R.id.img2);

        ll = (LinearLayout)findViewById(R.id.ll);

        s = (HorizontalScrollView) findViewById(R.id.hsv);
        s.setDrawingCacheEnabled(true);

    }

     //Fired onClick of the button
       public void click(View v) {
           shoot();
       }

    // To capture layout, create a bitmap and replace an image with the resulting bitmap.
    public void shoot() {

        s.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);

        int totalHeight = s.getMeasuredHeight();
        int totalWidth = s.getMeasuredWidth();

        s.layout(0, 0, totalHeight, totalWidth);    
        s.buildDrawingCache(true);

        Bitmap b = Bitmap.createBitmap(s.getDrawingCache());             
        s.setDrawingCacheEnabled(false);

        img1.setImageBitmap(b);     
    }

Я не получаю правильную высоту и ширину макета, если не использую MeasureSpec.

При нажатии кнопки я получаю изображение только половины кнопки. Я думаю, что это происходит, поскольку я не использую ViewTreeObserver. Но когда я использую ViewTreeObserver, я не получаю результата. Кроме того, приложение вылетает, когда я дважды нажимаю кнопку - NullPointerException в Bitmap.

Я пробовал почти все, что доступно на StackOverFlow. Пожалуйста, помогите мне найти способ сделать это. Это вообще возможно?


person Niket Singh    schedule 09.01.2013    source источник


Ответы (2)


Нашел ПРОСТОЙ способ сделать это.

XML

        <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal"
    android:layout_gravity="center_vertical">

     <HorizontalScrollView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            >

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

    <Button 
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:text="capture"
        android:onClick="click"/>

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <ImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/black"
        android:id="@+id/img"/>

    <ImageView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/a"/>

    </LinearLayout>

    </HorizontalScrollView>

</LinearLayout>

Код активности:

public class CaptureBeyondActivity extends Activity {
/** Called when the activity is first created. */

LinearLayout def;
ImageView img;
HorizontalScrollView hsv;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

def = (LinearLayout)findViewById(R.id.def);
img = (ImageView)findViewById(R.id.img);

}

public void click(View v) {
Bitmap bitmap;
def.setDrawingCacheEnabled(true);
def.buildDrawingCache(true);

        bitmap = Bitmap.createBitmap(def.getWidth(), def.getHeight(),
                Config.ARGB_8888);
        def.layout(0, 0, def.getLayoutParams().width,
                def.getLayoutParams().height);
        Canvas c = new Canvas(bitmap);
        def.draw(c);

def.setDrawingCacheEnabled(false);

if(bitmap!=null){
    img.setImageBitmap(bitmap);
    img.invalidate();
}
}}

Здесь я поместил некоторые элементы в HorizontalScrollView. При нажатии кнопки делается снимок экрана, а второе изображение заменяется сделанным снимком экрана. Он также делает скриншоты закадровых элементов. Вы можете дополнительно улучшить код и сохранить окончательное растровое изображение на SD-карте.

person Niket Singh    schedule 23.07.2013

это второй раз, когда я вижу этот же вопрос (да, здесь, в переполнении стека), и простой ответ: нет простого способа сделать это!

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

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

person Budius    schedule 09.01.2013
comment
Спасибо. Можете ли вы предложить мне что-то, с чем я могу уменьшить масштаб всего содержимого прокрутки, чтобы он соответствовал экрану, а затем сделать снимок экрана. Если это возможно, то любой ответ будет очень полезен. - person Niket Singh; 09.01.2013
comment
Нашел способ. Пожалуйста, обратитесь к моему ответу. - person Niket Singh; 23.07.2013