Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android restrict the size when text sizing with pinch zoom and temp image

There are texts on my static layout, the layout is an item in a Recyclerview. The touch event of the Recyclerview class controls the pinch zoom to the text with ScaleGestureDetector. The zooming senario is, when the user action move the screen of Recyclerview, getting the screenshot of the recyclerview and displaying the image over the Recyclerview, and the user zooming to the image. When the action up, applying new text size that coming from scaling to the items. The new text size is should be same with when the zooming to image displaying text size. For this I use RelativeSizeSpan and float scaler value. I want to limit the total text size changing but it just doesn't happen.

enter image description here

The real problem is, the pinch zoom can be done more than once and it is necessary to collect the scaling that each of them because the pinch zoom reseting each action pointer up. (mScaleFactor = 1.0f) And the all of scaling shouldn't cross the specified limit. (MAX_ZOOM and MIN_ZOOM)

Recyclerview:

private ScaleListener mScaleListener;
private ScaleGestureDetector mScaleGestureDetector;

@Override
public boolean onTouchEvent(MotionEvent event) {
    int action = event.getAction() & MotionEvent.ACTION_MASK;

    if(event.getPointerCount() == 2 && (action == MotionEvent.ACTION_MOVE || action == MotionEvent.ACTION_POINTER_UP)) {
        if(mScaleGestureDetector == null){
            mScaleListener = new ScaleListener(mRecyclerview, mContext);
            mScaleGestureDetector = new ScaleGestureDetector(mContext, mScaleListener);
        } return mScaleGestureDetector.onTouchEvent(event);

    }

}

Adapter:

private void changeTextSize(float mScaleFactor){
    ...
    float newFontSize = (relativeSizeSpan.getSizeChange() * mScaleFactor);
    ...
}

ScaleListener:

public class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    private static final float MAX_ZOOM = 2.5f;
    private static final float MIN_ZOOM = 0.5f;
    private float mScaleFactor = 1.0f;
    private ImageView mScreenShotView;
    private Context mContext; 
    private View mView;

    public ScaleListener(View mView, Context mContext) {
        this.mView = mView;
        this.mContext = mContext;
        init();
    }

    private void init(){
        int mWidth = mView.getWidth();
        int mHeight = mView.getHeight();
        if(mWidth == 0 || mHeight == 0) return;

        mScreenShotView = new ImageView(mContext);
        mScreenShotView.setLayoutParams(new ViewGroup.LayoutParams(mWidth, mHeight));

        ViewGroup mPhysicalParentLayout = (ViewGroup) mView.getParent();
        mPhysicalParentLayout.addView(mScreenShotView, mPhysicalParentLayout.indexOfChild(mView));
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        mScreenShotView.setBackgroundDrawable(new BitmapDrawable(Kit.getScreenshot(mView)));
        mScreenShotView.setAlpha(1f); mView.setAlpha(0f);
        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector){
        mScaleFactor *= scaleGestureDetector.getScaleFactor();

        mScaleFactor = Math.max(MIN_ZOOM, Math.min(mScaleFactor, MAX_ZOOM));

        mScreenShotView.setScaleX(mScaleFactor);
        mScreenShotView.setScaleY(mScaleFactor);

        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {

        ((ReadBookRcAdapter)Objects.requireNonNull(((RecyclerView)mView).getAdapter())).changeTextSize(mScaleFactor);

        mScreenShotView.animate().alpha(0f).setDuration(300).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) { 
                mView.animate().alpha(1f).setDuration(300).setListener(null); 
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                mScreenShotView.setScaleX(1.0f);
                mScreenShotView.setScaleY(1.0f);
                mScaleFactor = 1.0f;
            }
        });

    }


}
like image 533
ATES Avatar asked Jun 01 '20 13:06

ATES


1 Answers

Solved the issue with restricting value of TextView.setTextSize(). It's my adapter class:

public class ReadBookRcAdapter extends RecyclerView.Adapter<ReadBookRcAdapter.ReadBookViewHolder> {

    private Context mContext;
    private ArrayList<ReadBookTextBlockModel> mTextViewBlocks;
    private float mTextSize;

    public ReadBookRcAdapter(Context context) {
        this.mContext = context;
        this.mTextViewBlocks = new ReadBookTextBlockModel(context).getTextBlocks();
        mTextSize = 15.0f;
    }

    class ReadBookViewHolder extends RecyclerView.ViewHolder {
        TextView mTextViewItem;

        ReadBookViewHolder(@NonNull View itemView) {
            super(itemView);
            this.mTextViewItem = itemView.findViewById(R.id.readBookTextRow);
        }

        void bind(ReadBookTextBlockModel dataList){
            if (mTextSize != 15.0f) mTextViewItem.setTextSize(mTextSize);
            mTextViewItem.setText(dataList.getBlockText());
        }

    }

    @NonNull
    @Override
    public ReadBookViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rc_item_read_book, parent, false);
        return new ReadBookViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ReadBookViewHolder holder, int position) {
        ReadBookTextBlockModel model = mTextViewBlocks.get(position);
        holder.bind(model);
    }

    public void setTextSize(float scale){

        float maxTextSize = 37.5f;
        float minTextSize = 7.5f;

        if((mTextSize == minTextSize && scale < 1.0f) || (mTextSize == maxTextSize && scale >= 1.0f))
            return;

        float newTextSize = mTextSize * scale;
        newTextSize = Math.max(minTextSize, Math.min(newTextSize, maxTextSize));

        mTextSize = newTextSize;

        Log.e("mTextSize*scale", String.valueOf(mTextSize));

        notifyDataSetChanged();
    }

}
like image 123
ATES Avatar answered Oct 19 '22 23:10

ATES