Android - scale font size of textview with pinch zoom - android

I am trying to scale a TextView with a pinch-zoom gesture. I have the pinch zoom working, but as the text scales it becomes somewhat pixelated. I assume this is because the actual font size is not scaling. However, when I try to put setTextSize() anywhere inside the onTouch() method, it scales very choppy with little lines appearing/disappearing on the edge of the TextView and the text disappearing when scale sufficiently large. I have the TextView inside a LinearLayout, and the pinch zoom scales the LinearLayout.
Here is the layout xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF000000" >
<LinearLayout
android:id="#+id/textLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="top"
android:text="texthere" />
</LinearLayout>
<View
android:id="#+id/touchView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
Here is the touch listener java:
scaleView.setOnTouchListener(new View.OnTouchListener(){
public boolean onTouch(View v, MotionEvent event){
float viewWidth = mTextView.getWidth();
float viewHeight = mTextView.getHeight();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mode = DRAG;
x_0 = mTextView.getX();//+50;
y_0 = mTextiew.getY();//+50;
initialTouchRawX = event.getRawX();
initialTouchRawY = event.getRawY();
currentScale = mTextView.getScaleX();
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist2 = spacing(event);
if (oldDist2 > 10f) {
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
float xmin = x_0 - viewWidth/2*(currentScale-1);
float xmax = x_0 + viewWidth + viewWidth/2*(currentScale-1);
float ymin = y_0 - viewHeight/2*(currentScale-1) + viewShift;
float ymax = y_0 + viewHeight + viewHeight/2*(currentScale-1) + viewShift;
if (mode == DRAG && initialTouchRawX >= xmin && initialTouchRawX <= xmax && initialTouchRawY >= ymin && initialTouchRawY <= ymax ) {
float mShiftX = -(initialTouchRawX - x_0);
float mShiftY = -(initialTouchRawY - y_0);
mTextView.setX((float) event.getRawX()+mShiftX);
mTextView.setY((float) event.getRawY()+mShiftY);
} else if (mode == ZOOM) {
float newDist2 = spacing(event);
if (newDist2 > 10f) {
newScale = newDist2 / oldDist2 * currentScale;
mTextView.setScaleX(newScale);
mTextView.setScaleY(newScale);
//***I've tried setting the font size here***
}
}
break;
}
//***I've tried setting the font size here***
//*** Now I write the scaling float to shared preferences here
return true;
}
});
I am confounded about where and how to actually scale the font size. I've indicated in the code where I have tried implementing setFontSize(). I mean, it did work, for the most part, but like I mentioned above, it was very bad quality with text disappearing and the lines sometimes appearing on the edge of the TextView. Any hints are much appreciated.
=== EDIT: ===
I've implemented a custom TextView below:
public class ScaleTextView extends TextView {
public ScaleTextView(Context context) {
this(context, null);
}
public ScaleTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScaleTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
updateTextSize(context);
}
public void updateTextSize(Context context) {
getTypeface();
float currentTextSize = getTextSize();
SharedPreferences otherSettings = context.getSharedPreferences("settings", 0);
float newScale = otherSettings.getFloat("key_scaling", 1f);
setTextSize(newScale * currentTextSize);
}
}
So this helps somewhat except that the font size is now different for portrait and landscape, and this causes the scaling to change each time orientation is changed. The text still disappears once scale sufficiently large and there are lines on the edge of the textview sometimes. Maybe there is a betterway to pass the scaling variable to the custom ScaleTextView class?

Related

How to create an endeless / moveable Layout? "endless paper"-Metapher

how do i create an endless / movable layout, which is endless/movable in all directions?
I want to develop an app to create diagrams, and if the diagram gets too big i want it to be movable in all directions.
I hope its understandable.
with regards
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw);
_root = (ViewGroup) findViewById(R.id.draw);
_view = new ImageView(this);
_view.setImageResource(R.drawable.greenbutton);
BitmapDrawable bd=(BitmapDrawable) this.getResources().getDrawable(R.drawable.greenbutton);
int height=bd.getBitmap().getHeight();
int width=bd.getBitmap().getWidth();
/*MyScrollView myV = new MyScrollView(this);
myV.setLayoutParams(_root.getLayoutParams());*/
RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(height,width);
_view.setLayoutParams(layoutParams);
_view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
v.setLayoutParams(layoutParams);
break;
}
_root.invalidate();
return true;
}
});
//myV.addView(_view);
_root.addView(_view);
<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="horizontal"
tools:context=".Draw">
<RelativeLayout
android:id="#+id/draw"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/layout_grid">
</RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="5"
android:orientation="vertical">
<GridView
android:id="#+id/mostUsedBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="2"
android:layout_weight="1">
</GridView>
<GridView
android:id="#+id/elementBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="2"
android:layout_weight="1"></GridView>
<GridView
android:id="#+id/relBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="2"
android:layout_weight="1"></GridView>
</LinearLayout>
</LinearLayout>
Create a custom view that scrolls (do it manually) and keep everything in two variables let's say scrollX and scrollY (assume the point at the top left point of the screen). So draw everything on top with an offset of scrollX and scrollY.
Here is some code:
public class MyScrollView extends View
{
private int scrollX, scrollY;
private int pinPointX, pinPointY;
public MyScrollView(Context context)
{
super(context);
//Initialize scroll to look at the top left edge of the "paper"
scrollX = 0;
scrollY = 0;
}
public void onTouchEvent(MotionEvent e)
{
switch (e.getAction())
{
case MotionEvent.ACTION_DOWN:
//Mark touch point
pinPointX = (int) e.getX();
pinPointY = (int) e.getY();
break;
case MotionEvent.ACTION_MOVE:
//Scroll view
scrollX += (int) e.getX() -pinPointX;
scrollY += (int) e.getY() -pinPointY;
//Mark new point
pinPointX = (int) e.getX();
pinPointY = (int) e.getY();
break;
}
}
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//Draw everything here with an offset of scrollX, scrollY
}
}
Sorry I may have made some mistakes (mainly with android's class names) but I wrote the code on the go, if u see any minor mistake make sure to correct it.
Note that this code will allow you to scroll "infinitely" at least as long as scrollX and scrollY remain on their int limits (from -2,147,483,648 to 2,147,483,647) you can keep it like that since nobody will scroll that far, but I'd recommend applying some limits just to make the app more "perfect".
Also I'm not sure but I think this code may have some issue if you scroll to the negative side (leftwards and upwards - when scrollX and/or scrollY are negative) but I may be wrong.
If you want to include more views (like a layout that you ask) make it a ViewGroup but I don't have much experience using that. I showed you a logic to follow it's up to you to attach it to your code as you like.

Android stretch background image while dragging the imageview

I am try to implement the vertical slider of image control. The image is inside the ScrollView. When it comes to vertical dragging of ImageView, the top margin of relative layout always provide different reading.
If it is greater than 600 something while dragging down, the background image of the relative layout stretch vertically together with the image position I have dragged.
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:fillViewport="true" >
...
<RelativeLayout
android:id="#+id/relativeLayouyt6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/rTop"
android:background="#drawable/plain" >
<ImageView
android:id="#+id/dragImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/arrow_one"
android:visibility="gone" />
</RelativeLayout>
Would you please tell me how to
get the offset I have scrolled in my scrollview ?
I know it is get touch position minus scrolled position and plus image Y position, how to implement this parameter after finishing dragging ?
How to set relative boundary for imageview inside the relative layout ? is it wiser to take this background image out as the imageview?
If I programmatically repositioning of 6 relativelayouts but coming up to the same width , would it affect the scrolling position and the scollview total Height ? If so , How to calculate the offset Y for the repositioning ?
The below is my code as of February 11:
dragImage.setOnTouchListener(new OnTouchListener(){
//private int _xDelta;
private int _yDelta;
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
final float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//_yDelta = Y - lParams.topMargin;
mOldY2 = y;
break;
case MotionEvent.ACTION_UP:
mViewPager.setPagingEnabled(true);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
btn4.setBackgroundResource(R.drawable.fbl02);
final float dy = y - mOldY2;
mNewY2 += dy;
mOldY2 = y;
System.out.println(mNewY2);
while(mNewY2 > 224){
mNewY2 -= 224;
}
while(mNewY2 < 157){
mNewY2 += 157;
}
if(mNewY2 < 157 || mNewY2 > 224)
break;
v.setTranslationY((int)mNewY2);
v.invalidate();
float power = (float) ( 51.5/67 -(0.2/67) * mNewY2) ;
System.out.println(power);
Float roundF = new Float( Math.round(power));
midBandStick = roundF;
btn4.setText(String.valueOf(midBandStick) );
//}
//break;
}
return true;
}
The below is my code :
public static void setRLBelowAnother(RelativeLayout rA , RelativeLayout rB ){
RelativeLayout.LayoutParams rparam4 =
(android.widget.RelativeLayout.LayoutParams) rB.getLayoutParams();
rparam4.addRule(RelativeLayout.BELOW, rA.getId());
rB.setLayoutParams(rparam4);
}
setRLBelowAnother(rTop , r1);
setRLBelowAnother(r1 , r2);
setRLBelowAnother(r2 , r6 );
setRLBelowAnother(r6 , r3 );
setRLBelowAnother(r3 , r4 );
setRLBelowAnother(r4 , r5 );
dragImage.setVisibility(View.VISIBLE);
dragImage.setImageResource(R.drawable.slide_lshort);
dragImage.setX((float) (0.15*screenWidth));
dragImage.setY((float) (0.05*screenHeight));
dragImage.setOnTouchListener(new OnTouchListener(){
//private int _xDelta;
private int _yDelta;
#Override
public boolean onTouch(View v, MotionEvent event) {
v.getParent().requestDisallowInterceptTouchEvent(true);
final int X = (int) event.getX();
final int Y = (int) event.getY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) dragImage
.getLayoutParams();
//_xDelta = X - lParams.leftMargin;
_yDelta = Y - lParams.topMargin;
break;
case MotionEvent.ACTION_UP:
mViewPager.setPagingEnabled(true);
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
midStick = 0.2f;
btn4.setBackgroundResource(R.drawable.fbl02);
RelativeLayout.LayoutParams ParamsA = (RelativeLayout.LayoutParams) dragImage
.getLayoutParams();
//ParamsA.leftMargin = X - _xDelta;
ParamsA.topMargin = Y - _yDelta;
//ParamsA.rightMargin = -250;
ParamsA.bottomMargin = -250;
mViewPager.setPagingEnabled(false);
int offYb = 0;
int pos = ParamsA.topMargin + offYb ;
if(pos > -52 && pos < 582 ){
dragImage.setLayoutParams(ParamsA);
System.out.println(ParamsA.topMargin);
float power = (float) (100 + (900/634) * ParamsA.topMargin) ;
Float roundF = new Float( Math.round(power));
midStick = roundF;
btn4.setText(String.valueOf(midStick));
}
break;
}
return true;
}
});
Call the getScrollY() method from the ScrollView to get the Y index (scrolled index)
If I understood (otherwise please correct me) you could get a frame (boundary) between the ImageView and the RelativeLayout adding padding or margin to the ImageView. You just need to call android:padding="" or android:margin=""
The height of the ScrollView will change and also the scrollY if the new added RelativeLayout/ImageView doesn't completely fit on the available space. When you finish adding the new layout you could get the scrollY from the ScrollView and see where the ScrollView has scrolled to.
Can you improve the questions 2, 3 and 4? It's quite confusing.

Android: Limiting Layout Scroll Range

I would like to set a limit the the x and y ranges of a scrollable image. Here is the code I am using:
public class MapActivity extends Activity {
private LinearLayout container;
private int currentX;
private int currentY;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
container = (LinearLayout) findViewById(R.id.Container);
container.scrollTo(0, 0);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
currentX = (int) event.getRawX();
currentY = (int) event.getRawY();
break;
}
case MotionEvent.ACTION_MOVE: {
int x2 = (int) event.getRawX();
int y2 = (int) event.getRawY();
container.scrollBy(currentX - x2 , currentY - y2);
currentX = x2;
currentY = y2;
break;
}
case MotionEvent.ACTION_UP: {
break;
}
}
return true;
}
}
And my map.xml looks like this.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<LinearLayout
android:id="#+id/Container"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<ImageView
android:id="#+id/imageView1"
android:src="#drawable/aowmap"
android:layout_height="752px"
android:layout_width="1712px"></ImageView>
</LinearLayout>
</LinearLayout>
I've tried various ways to get "Container"s x and y and even the images x and y, but no luck. I'm sure the code would go under ACTION_UP, but I'm just not sure what to put there to find the x and y.
You need to have a look at the display metrics, below is a snippet of code I use in an image gallery to restrict scrolling left, you should be able to do something similar!
The key line is mlp.setMargins(...), the first parameter passed to that function is where i set the new left margin so you would need to do something similar but for the bottom margin!
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
MarginLayoutParams mlp = (MarginLayoutParams) gallery.getLayoutParams();
mlp.setMargins(-(metrics.widthPixels/2+130),mlp.topMargin,mlp.rightMargin, mlp.bottomMargin );
Hope this helps! :)

Android: How to perform zoom on two imageviews in android?

I have two images inside my layout. I need to zoom that image which i touched. We know that Frame can display a single view at a time. So how do i perform zoom on each imageview separately ? My xml file :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:src="#drawable/image1" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" android:src="#drawable/image2"
/>
</FrameLayout>
Activity file :
public class MyActivity extends Activity implements OnTouchListener
{
private static final String TAG = "Touch";
// These matrices will be used to scale points of the image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// The 3 states (events) which the user is trying to perform
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// these PointF objects are used to record the point(s) the user is touching
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
private ImageView iv1;
private ImageView iv2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
iv1 = ((ImageView)findViewById(R.id.imageView1));
iv1.setOnTouchListener(this);
iv2 = ((ImageView)findViewById(R.id.imageView2));
iv2.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.imageView1:
zoomImageView(v, event);
break;
case R.id.imageView2:
zoomImageView(v, event);
break;
default:
break;
}
return true;
}
private boolean zoomImageView(View v, MotionEvent event) {
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
switch (event.getAction() & 255)
{
case MotionEvent.ACTION_DOWN: // first finger down only
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG"); // write to LogCat
mode = DRAG;
break;
case MotionEvent.ACTION_UP: // first finger lifted
case 6: // second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case 5: // first and second finger down
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix of points
}
else if (mode == ZOOM)
{
// pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f)
{
matrix.set(savedMatrix);
scale = newDist / oldDist; // setting the scaling of the
// matrix...if scale > 1 means
// zoom in...if scale < 1 means
// zoom out
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix); // display the transformation on screen
return true; // indicate event was handled
}
private float spacing(MotionEvent event)
{
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
/*
* --------------------------------------------------------------------------
* Method: midPoint Parameters: PointF object, MotionEvent Returns: void
* Description: calculates the midpoint between the 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);
}
}
Now i'am able zoom only image1 which is on top. How do i get the zoom functionality for bottom image on touch of image2 ? I should be able to zoom the image on which i touched. Please help me.
You can use LinearLayout and align them horizontally or vertically in this way you will have two imageviews which are independent with each other
then use gestureimageview which supports panning zooming and and double tap see link below....
hope this answers your question :D
Click here!
https://github.com/jasonpolites/gesture-imageview
Use ZoomageView instead of ImageView.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.jsibbold.zoomage.ZoomageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:src="#drawable/image1" />
<com.jsibbold.zoomage.ZoomageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:src="#drawable/image2" />
</FrameLayout>
Add dependencies :
implementation 'com.jsibbold:zoomage:1.1.0'
Hope this will help you.

Android: Scrolling an Imageview

I have an ImageView that is twice the height of a normale screen ( 960 dip). I would like to scroll it nicely up and down on the screen. The bottom of the screen should contain a button. I have tried various combinations of ScrollView and Imageviews without any success. I have also thinkered with the :isScrollContainer attribute without results. Anyone knows how to do this?
Cheers,
Luca
#cV2 Thank you so much for that code. It got me going in the direction I needed. Here's my modified version which stops scrolling at the edges of the image...
// set maximum scroll amount (based on center of image)
int maxX = (int)((bitmapWidth / 2) - (screenWidth / 2));
int maxY = (int)((bitmapHeight / 2) - (screenHeight / 2));
// set scroll limits
final int maxLeft = (maxX * -1);
final int maxRight = maxX;
final int maxTop = (maxY * -1);
final int maxBottom = maxY;
// set touchlistener
ImageView_BitmapView.setOnTouchListener(new View.OnTouchListener()
{
float downX, downY;
int totalX, totalY;
int scrollByX, scrollByY;
public boolean onTouch(View view, MotionEvent event)
{
float currentX, currentY;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
currentX = event.getX();
currentY = event.getY();
scrollByX = (int)(downX - currentX);
scrollByY = (int)(downY - currentY);
// scrolling to left side of image (pic moving to the right)
if (currentX > downX)
{
if (totalX == maxLeft)
{
scrollByX = 0;
}
if (totalX > maxLeft)
{
totalX = totalX + scrollByX;
}
if (totalX < maxLeft)
{
scrollByX = maxLeft - (totalX - scrollByX);
totalX = maxLeft;
}
}
// scrolling to right side of image (pic moving to the left)
if (currentX < downX)
{
if (totalX == maxRight)
{
scrollByX = 0;
}
if (totalX < maxRight)
{
totalX = totalX + scrollByX;
}
if (totalX > maxRight)
{
scrollByX = maxRight - (totalX - scrollByX);
totalX = maxRight;
}
}
// scrolling to top of image (pic moving to the bottom)
if (currentY > downY)
{
if (totalY == maxTop)
{
scrollByY = 0;
}
if (totalY > maxTop)
{
totalY = totalY + scrollByY;
}
if (totalY < maxTop)
{
scrollByY = maxTop - (totalY - scrollByY);
totalY = maxTop;
}
}
// scrolling to bottom of image (pic moving to the top)
if (currentY < downY)
{
if (totalY == maxBottom)
{
scrollByY = 0;
}
if (totalY < maxBottom)
{
totalY = totalY + scrollByY;
}
if (totalY > maxBottom)
{
scrollByY = maxBottom - (totalY - scrollByY);
totalY = maxBottom;
}
}
ImageView_BitmapView.scrollBy(scrollByX, scrollByY);
downX = currentX;
downY = currentY;
break;
}
return true;
}
});
I'm sure it could be refined a bit, but it works pretty well. :)
I searched so long for this Code, so I wanted to share this great peace of code:
this code is from an Activity, which has a xml file on the backend containing an ImageView called 'img'
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/img"
android:scaleType="center"
android:background="#fff"
android:src="#drawable/picName"
/>
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xml_name_layout);
final ImageView switcherView = (ImageView) this.findViewById(R.id.img);
switcherView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View arg0, MotionEvent event) {
float curX, curY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
mx = curX;
my = curY;
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
switcherView.scrollBy((int) (mx - curX), (int) (my - curY));
break;
}
return true;
}
});
}
did the job perfectly for me...
horizontal & vertical scrolling included (enabled)
only negative side is... you can scroll over the edge of the picture...
but this is no problem for me.. and spending some time you could easily implement this feature :)
good luck && have fun
this is how I fixed it :p
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarAlwaysDrawVerticalTrack="true">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="Specs"
android:scrollbars="vertical"
android:src="#drawable/image"/>
</ScrollView>
#wirbly Thank you so much for your code, it works exactly the way I want.
But when i first read your code, I was a little confused about the four variables that you forgot to define .
So, i want to add the definition for the code to make it clearer.
Resources res=getResources();
Bitmap mBitmap = BitmapFactory.decodeResource(res, R.drawable.p_1920x1080);
BitmapDrawable bDrawable = new BitmapDrawable(res, mBitmap);
//get the size of the image and the screen
int bitmapWidth = bDrawable.getIntrinsicWidth();
int bitmapHeight = bDrawable.getIntrinsicHeight();
int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth();
int screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();
Hope it's helpful.
The easiest way is imho to use a webview and load the image into it via a local html file. This way you will also automatically get the zoom controls if you want to use them.
For a large image (i.e. if it's 1000 or 3000 px wide) you will notice that Android (Coliris) isn't very good at displaying large zoomed images very sharp, even if the original images is sharp and uncompressed). This is a known issue. The solution for that is to break down the large image into smaller tiles and put them together again via html (div's or table).
I use this approach to provide a subway map (larger than the screen and scrollable) to the user.
WebView webView = (WebView)findViewById(R.id.webView);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
webView.loadUrl( "content://com.myapp.android.localfile/sdcard/myappdata/common/mtr_map.html");
This might work for most cases / 'regular apps', although depends on your particular case. If you are talking about a image as a scrollable background of a game, it might not be useful for you.
Instead of a html file, you could also load the image directly (png, jpg). If you don't want the zoom control, just turn them off.
Another way is to create a HorizontalScrollView, add the imageView into it and then add the HorizontalScrollView into a ScrollView. This allows you to scroll up, down, left, right.
it works for me
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/img"
android:scaleType="centerCrop"
android:adjustViewBounds="true"/>
<Button
style="#style/btn"
android:id="#+id/btn"
android:layout_height="60dp"
android:layout_marginTop="20dp"
android:background="#drawable/btn"
android:onClick="click"
android:text="text" />
</LinearLayout>
</ScrollView>
hey guys found an easy and 100% reliable solution as Mr X mentioned above(as the other codes mentioned weren't working working on some devices or breaking)
Simply use ScrollView provided by android and it takes care of stuff
something like this
<ScrollView android:layout_width="fill_parent" android:id="#+id/scrollView1"
android:layout_height="wrap_content" android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" android:layout_above="#+id/button1"
android:layout_alignParentRight="true" android:scrollbarAlwaysDrawVerticalTrack="true">
<LinearLayout android:id="#+id/linearLayout1"
android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal">
<ImageView android:src="#android:drawable/ic_menu_report_image"
android:layout_height="wrap_content" android:id="#+id/imageView1"
android:layout_width="wrap_content"></ImageView>
</LinearLayout>
</ScrollView>
and in oncreate something like this
if (mImageName != null) {
InputStream is = null;
try {
is = this.getResources().getAssets().open("mathematics/"+mImageName);
} catch (IOException e) {
}
Bitmap image = BitmapFactory.decodeStream(is);
mImageView.setImageBitmap(image);
}
Cheers!

Categories

Resources