I have a view-group (ZoomableViewGroup
is my custom class extending ViewGroup
) in my layout as parent, which inside contains a relative layout. The width and height of ViewGroup
is by default 2286 height and 1600 width which is larger than device size. How to set the ViewGroup
size to screen size ? My final expected result is, I am trying to zoom and pan the relative out, it moves out of screen due to the huge size of ViewGroup
.
<com.example.pdoc.zoomablepdf.ZoomableViewGroup
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/zoomLayout"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@drawable/samplebg"
android:id="@+id/RelLayout">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/LinLayout">
</LinearLayout>
</RelativeLayout>
</com.example.pdoc.zoomablepdf.ZoomableViewGroup>
Java code
ZoomableViewGroup mZoomableViewGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mainnew);
mZoomableViewGroup = (ZoomableViewGroup) findViewById(R.id.zoomLayout);
LinearLayout ll = (LinearLayout)findViewById(R.id.LinLayout);
//add edittext dynamically
EditText myText = new EditText(MainnewActivity.this);
myText.setText("Edit Me");
LinearLayout.LayoutParams lp = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lp.gravity= Gravity.CENTER_HORIZONTAL;
ll.addView(myText, lp);
//add checkbox dynamically
CheckBox myChk = new CheckBox(MainnewActivity.this);
myChk.setText("Check me");
LinearLayout.LayoutParams chklp = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
chklp.gravity= Gravity.CENTER_HORIZONTAL;
ll.addView(myChk, chklp);
//add imageview dynamically
ImageView myImg = new ImageView(MainnewActivity.this);
myImg.setImageResource(R.drawable.apple);
LinearLayout.LayoutParams imgLP = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
imgLP.gravity= Gravity.CENTER_HORIZONTAL;
ll.addView(myImg, imgLP);
//add button dynamically
Button mybtn1 = new Button(MainnewActivity.this);
mybtn1.setText("Click me");
LinearLayout.LayoutParams btnLP = new
LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
btnLP.gravity= Gravity.CENTER_HORIZONTAL;
ll.addView(mybtn1, btnLP);
mybtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainnewActivity.this, "6--"+ mZoomableViewGroup.getHeight() + "_" + mZoomableViewGroup.getWidth(),Toast.LENGTH_SHORT).show();
}
});
}
ZoomableViewGroup class code
public class ZoomableViewGroup extends ViewGroup {
// States.
private static final byte NONE = 0;
private static final byte DRAG = 1;
private static final byte ZOOM = 2;
private static final byte DTAP = 3;
private byte mode = NONE;
// Matrices used to move and zoom image.
private Matrix matrix = new Matrix();
private Matrix matrixInverse = new Matrix();
private Matrix savedMatrix = new Matrix();
// Parameters for zooming.
private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float[] lastEvent = null;
private long lastDownTime = 0l;
private float[] mDispatchTouchEventWorkingArray = new float[2];
private float[] mOnTouchEventWorkingArray = new float[2];
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mDispatchTouchEventWorkingArray[0] = ev.getX();
mDispatchTouchEventWorkingArray[1] = ev.getY();
mDispatchTouchEventWorkingArray = screenPointsToScaledPoints(mDispatchTouchEventWorkingArray);
ev.setLocation(mDispatchTouchEventWorkingArray[0], mDispatchTouchEventWorkingArray[1]);
return super.dispatchTouchEvent(ev);
}
public ZoomableViewGroup(Context context) {
super(context);
Toast.makeText(context, "c1-" + this.getHeight() + "_" + this.getWidth(), Toast.LENGTH_SHORT).show ();
init(context);
}
public ZoomableViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
Toast.makeText(context, "c2-" + this.getHeight() + "_" + this.getWidth(), Toast.LENGTH_SHORT).show ();
init(context);
}
public ZoomableViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
Toast.makeText(context, "c3-" + this.getHeight() + "_" + this.getWidth(), Toast.LENGTH_SHORT).show ();
init(context);
}
private void init(Context context) {
}
//Determine the space between the first two fingers
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
//Calculate the mid point of the first two fingers
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
private float[] scaledPointsToScreenPoints(float[] a) {
matrix.mapPoints(a);
return a;
}
private float[] screenPointsToScaledPoints(float[] a) {
matrixInverse.mapPoints(a);
return a;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//super.onLayout(changed, left, top, right, bottom);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
child.layout(child.getLeft(), child.getTop(), child.getLeft()+child.getMeasuredWidth(), child.getTop()+child.getMeasuredHeight());
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//measure(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
//measure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void dispatchDraw(Canvas canvas) {
float[] values = new float[9];
matrix.getValues(values);
canvas.save();
canvas.translate(values[Matrix.MTRANS_X], values[Matrix.MTRANS_Y]);
canvas.scale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]);
super.dispatchDraw(canvas);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// handle touch events here
mOnTouchEventWorkingArray[0] = event.getX();
mOnTouchEventWorkingArray[1] = event.getY();
mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);
event.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
mode = DRAG;
lastEvent = null;
long downTime = event.getDownTime();
if (downTime - lastDownTime < 300l) {
float density = getResources().getDisplayMetrics().density;
if (Math.max(Math.abs(start.x - event.getX()), Math.abs(start.y - event.getY())) < 20.f * density) {
savedMatrix.set(matrix);
mid.set(event.getX(), event.getY());
mode = ZOOM;
lastEvent = new float[4];
lastEvent[0] = lastEvent[1] = event.getX();
lastEvent[2] = lastEvent[3] = event.getY();
}
lastDownTime = 0l;
} else {
lastDownTime = downTime;
}
start.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
final float density = getResources().getDisplayMetrics().density;
if (mode == DRAG) {
matrix.set(savedMatrix);
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
RelativeLayout Rel = (RelativeLayout)findViewById(R.id.RelLayout);
//getGlobalVisibleRect(Rel);
ZoomableViewGroup ZVG = (ZoomableViewGroup) findViewById(R.id.zoomLayout);
Rel.getTop();
Rel.getY();
//if(dx > 0) dx=0;
//if(dy > 0) dy=0;
//Toast.makeText(getContext(), dx + "_" + dy + "REL=" + Rel.getTop()+"_"+ Rel.getLeft(), Toast.LENGTH_SHORT).show ();
//Toast.makeText(getContext(), ZVG.getHeight() + "-" + ZVG.getWidth(), Toast.LENGTH_SHORT).show ();
matrix.postTranslate(dx, dy);
matrix.invert(matrixInverse);
if (Math.max(Math.abs(start.x - event.getX()), Math.abs(start.y - event.getY())) > 20.f * density) {
lastDownTime = 0l;
}
} else if (mode == ZOOM) {
if (event.getPointerCount() > 1) {
float newDist = spacing(event);
if (newDist > 10f * density) {
matrix.set(savedMatrix);
float scale = (newDist / oldDist);
//to restrict the min zoom not tobe less than screen size
float[] values = new float[9];
matrix.getValues(values);
if(scale*values[matrix.MSCALE_X] <= 1)
{ scale = 1/values[matrix.MSCALE_X]; }
//till here
//condition to check maximum zoom scale to 10
if(scale * values[matrix.MSCALE_X] <10)
matrix.postScale(scale, scale, mid.x, mid.y);
matrix.invert(matrixInverse);
}
} else {
matrix.set(savedMatrix);
float scale = event.getY() / start.y;
//to restrict the min zoom to 1 or not less than screen size
float[] values = new float[9];
matrix.getValues(values);
if(scale*values[matrix.MSCALE_Y] <= 1)
{ scale = 1/values[matrix.MSCALE_Y]; }
//till here
//condition to check maximum zoom scale to 10
if(scale * values[matrix.MSCALE_Y] <10)
matrix.postScale(scale, scale, mid.x, mid.y);
matrix.invert(matrixInverse);
}
}
break;
}
invalidate();
return true;
}
}