如何在内容滚动时捕获ScrollView的一部分?

时间:2016-02-16 14:45:41

标签: android bitmap scrollview capture

在扩展ScrollView课程后,我可以轻松地实时了解滚动信息。

现在我需要在非常具体的部分捕获此scrollview的内容。 让我们说我想捕捉屏幕的顶部(匹配父宽度和定义的高度,如100dp)。但是只有ScrollView的内容而不是其他内容,如果顶部有其他内容但不是ScrollView的一部分。

我尝试在scrollview上使用:

  1. setDrawingCacheEnabled(true);
  2. getDrawingCache(true);
  3. setDrawingCacheEnabled(false);
  4. 然后我尝试裁剪,以便得到我想要的部分:

    Bitmap.createBitmap(complete, 0, 0, width, height);

    结果与我想要实现的结果相差甚远,性能非常差,在某些时候我会尝试SIGENVgetDrawingCache(true)尝试使用循环位图...

    那么如何在没有太多性能影响的情况下轻松捕获所需区域中的内容?

    注意:此过程必须在我滚动内容时完成,因此在ScrollView的onScrollChanged(final int x, final int y)内。

    谢谢!

1 个答案:

答案 0 :(得分:1)

由于问题很有趣我实现了它,似乎工作正常。我想你每次重新创建一个Bitmap,为什么会变慢。

这个想法是这样的,你在ScrollView中创建了一个你要复制的区域(见Rect cropRectBitmap screenshotBitmap),它的全宽,你只需要设置高度。视图会自动在其自身上设置滚动侦听器,并在每个滚动条上复制该区域。请注意,setDrawingCacheEanbled(true)在实例化视图时只调用一次,它基本上告诉视图您将调用getDrawingCache(),这将返回视图正在绘制自身的位图。然后它会复制screenshotBitmap上感兴趣的区域,以及您可能想要使用的位图。

ScreenshottableScrollView.java

package com.example.lelloman.screenshottablescrollview;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.widget.ScrollView;

/**
 * Created by lelloman on 16-2-16.
 */
public class ScreenshottableScrollView extends ScrollView implements ViewTreeObserver.OnScrollChangedListener {

    public interface OnNewScreenshotListener {
        void onNewScreenshot(Bitmap bitmap);
    }

    private Bitmap screenshotBitmap = null;
    private Canvas screenshotCanvas = null;
    private int screenshotHeightPx = 0;
    private OnNewScreenshotListener listener = null;
    private Rect cropRect;
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);


    public ScreenshottableScrollView(Context context) {
        super(context);
        init();
    }

    public ScreenshottableScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init(){
        setDrawingCacheEnabled(true);
        getViewTreeObserver().addOnScrollChangedListener(this);
    }

    public void setOnNewScreenshotListener(OnNewScreenshotListener listener){
        this.listener = listener;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(screenshotHeightPx != 0)
            makeScrenshotBitmap(w,h);
    }

    public void setScreenshotHeightPx(int q){
        screenshotHeightPx = q;
        makeScrenshotBitmap(getWidth(), getHeight());
    }

    private void makeScrenshotBitmap(int width, int height){

        if(screenshotBitmap != null) screenshotBitmap.recycle();

        if(width == 0 || height == 0) return;

        screenshotBitmap = Bitmap.createBitmap(width, screenshotHeightPx, Bitmap.Config.ARGB_8888);
        screenshotCanvas = new Canvas(screenshotBitmap);

        cropRect = new Rect(0,0,width,screenshotHeightPx);


    }

    @Override
    public void onScrollChanged() {
        if(listener == null) return;

        Bitmap bitmap = getDrawingCache();

        screenshotCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

        screenshotCanvas.drawBitmap(bitmap,cropRect, cropRect,paint);
        listener.onNewScreenshot(screenshotBitmap);
    }
}

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:orientation="vertical"
    tools:context="com.example.lelloman.screenshottablescrollview.MainActivity">

    <com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView
        android:id="@+id/scrollView"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

    </com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView>
    <View
        android:layout_width="match_parent"
        android:layout_height="20dp"
        android:background="#ff000000"/>
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="100dp" />

</LinearLayout>

MainActivity.java

package com.example.lelloman.screenshottablescrollview;

import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Random;

public class MainActivity extends AppCompatActivity {

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

        StringBuilder builder = new StringBuilder();

        Random random = new Random();
        String AB = "abcdefghijklmnopqrstuvwxyz ";

        for(int i=0;i<100;i++){
            builder.append("\n\n"+Integer.toString(i)+"\n\n");
            for(int j =0;j<1000;j++){
                builder.append(AB.charAt(random.nextInt(AB.length())));
            }
        }

        ((TextView) findViewById(R.id.textView)).setText(builder.toString());
        final ImageView imageView = (ImageView) findViewById(R.id.imageView);

        ScreenshottableScrollView scrollView = (ScreenshottableScrollView) findViewById(R.id.scrollView);
        scrollView.setScreenshotHeightPx((int) (getResources().getDisplayMetrics().density * 100));

        scrollView.setOnNewScreenshotListener(new ScreenshottableScrollView.OnNewScreenshotListener() {
            @Override
            public void onNewScreenshot(Bitmap bitmap) {
                Log.d("MainActivity","onNewScreenshot");
                imageView.setImageBitmap(bitmap);
            }
        });
    }
}