I want to implement a movable imageView when it is drag. The dragging is working perfectly alright. But when i drag to the end , the imageView goes out of the screen. How can i make the movable of the imageview only inside the screen ?
This is my OnTouch listerner :
public boolean onTouch(View view, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_MOVE:
view.setY(event.getRawY() + dY);
view.setX(event.getRawX() + dX);
lastAction = MotionEvent.ACTION_MOVE;
break;
case MotionEvent.ACTION_UP:
if (lastAction == MotionEvent.ACTION_DOWN)
Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
break;
default:
return false;
}
return true;
}
and this is my layout. the layout contain a scrollview and their child, and the imageview which i want to drag.
<?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" >
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#ff0000"
android:gravity="center"
android:text="View 1"
android:textColor="#000"
android:textSize="100dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#00ff00"
android:text="View 2"
android:textColor="#000"
android:textSize="100dp" />
</LinearLayout>
</ScrollView>
<ImageView
android:id="#+id/draggable_view"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="20dp"
android:layout_marginEnd="20dp"
android:background="#drawable/icon" />
</FrameLayout>
After spend more time on it, finally find the best solution.
Modify my OnTouch listerner section as :
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHight = displaymetrics.heightPixels;
screenWidth = displaymetrics.widthPixels;
#SuppressLint("NewApi") #Override
public boolean onTouch(View view, MotionEvent event) {
float newX, newY;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
dX = view.getX() - event.getRawX();
dY = view.getY() - event.getRawY();
lastAction = MotionEvent.ACTION_DOWN;
break;
case MotionEvent.ACTION_MOVE:
newX = event.getRawX() + dX;
newY = event.getRawY() + dY;
// check if the view out of screen
if ((newX <= 0 || newX >= screenWidth-view.getWidth()) || (newY <= 0 || newY >= screenHight-view.getHeight()))
{
lastAction = MotionEvent.ACTION_MOVE;
break;
}
view.setX(newX);
view.setY(newY);
lastAction = MotionEvent.ACTION_MOVE;
break;
case MotionEvent.ACTION_UP:
if (lastAction == MotionEvent.ACTION_DOWN)
Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
break;
default:
return false;
}
return true;
}
It's working perfectly :)
After a lot of research, I found the best robust solution. The following code works perfectly for me keeping the ImageView or any View within Screen bounds.
Use the code in ACTION_MOVE
val pointerIndex = event.findPointerIndex(activePointerId)
if (pointerIndex == -1) return false
val (x, y) = event.getX(pointerIndex) to event.getY(pointerIndex)
posX += x - lastTouchX
posY += y - lastTouchY
// The BOUNDS_PADDING can be any value you like (Ex: 50)
val leftBound = -screenWidth + BOUNDS_PADDING
val rightBound = screenWidth - BOUNDS_PADDING
val downBound = -screenHeight + BOUNDS_PADDING
val upBound = screenHeight - BOUNDS_PADDING
if (posX <= leftBound) {
// Left Bound Reached while Dragging. So reset view position to be within bounds
posX = leftBound.toFloat()
}
if (posX >= rightBound) {
// Right Bound Reached while Dragging. So reset view position to be within bounds
posX = rightBound.toFloat()
}
if (posY <= downBound) {
// Bottom Bound Reached while Dragging. So reset view position to be within bounds
posY = downBound.toFloat()
}
if (posY >= upBound) {
// Top Bound Reached while Dragging. So reset view position to be within bounds
posY = upBound.toFloat()
}
binding.imageView.x = posX
binding.imageView.y = posY
lastTouchX = x
lastTouchY = y
You can obtain the screen width and height using the following
// Get Device Display Height and Width
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val wm = windowManager.currentWindowMetrics
val insets = wm.windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
screenWidth = wm.bounds.width() - insets.left - insets.right
screenHeight = wm.bounds.height() - insets.bottom - insets.top
} else {
val dm = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(dm)
screenWidth = dm.widthPixels
screenHeight = dm.heightPixels
}
Related
i'm trying to add a touch listener to FAB so that i can drag it any where in the FrameLayout, well my touch listener is working fine but the default position of the FAB is coming at top of the screen , i wanted it to be at the bottom right of the screen.
if i set the gravity to bottom,my touch listener wont work, how do get it dynamically ?
below is my woking code
Layout code
```
<FrameLayout
android:id="#+id/frame_layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/dashboard_foreground"
app:layout_behavior="#string/appbar_scrolling_view_behavior" >
<android.support.design.widget.FloatingActionButton
android:id="#+id/dash_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/mike"
app:fabSize="normal" />
</FrameLayout>
```
Activity
```
private int mTopMargin = 300;
mFab = (FloatingActionButton) findViewById(R.id.dash_fab);
FrameLayout.LayoutParams lpDraggableView = new
FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT);
mFab.setLayoutParams(lpDraggableView);
mFab.setOnTouchListener(OnTouchToDrag);
public View.OnTouchListener OnTouchToDrag = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
FrameLayout.LayoutParams dragParam = (FrameLayout.LayoutParams) v.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
if (((int) event.getRawY() - (v.getHeight() + mTopMargin)) > 0) {
dragParam.topMargin = (int) event.getRawY() - (v.getHeight() + mTopMargin);
TCLog.d("Custom", "topMargin" + ((int) event.getRawY() - (v.getHeight() + mTopMargin)));
dragParam.leftMargin = (int) event.getRawX() - (v.getWidth());
v.setLayoutParams(dragParam);
}
break;
}
case MotionEvent.ACTION_UP: {
// dragParam.height = 150;
// dragParam.width = 150;
dragParam.height = v.getHeight();
dragParam.width = v.getWidth();
dragParam.topMargin = (int) event.getRawY() - (v.getHeight() + mTopMargin);
dragParam.leftMargin = (int) event.getRawX() - (v.getWidth() / 2);
v.setLayoutParams(dragParam);
break;
}
case MotionEvent.ACTION_DOWN: {
break;
}
}
return true;
}
};
Even i tried the seting the Layout params dynamically, it is going out of the screen.
```
DisplayMetrics displayMetrics = getBaseContext().getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels ;
float dpWidth = displayMetrics.widthPixels ;
lpDraggableView.topMargin = dpHeight;
lpDraggableView.leftMargin = dpWIdth;
mFab.setLayoutParams(lpDraggableView);
```
You should calculate the position by yourself if you want to not use Gravity.
This is better aquired in the onResume method where the layout inflation and measurement already finished.
You may use display width and height if you want to do in onCreate.
If you have a custom view you may place your calculation code in the onMeasure method.
I am creating a rectangular box and putting an imageView inside it which can be moved. While doing onMove I noticed that imageView is going out of boundries of it's parent view which I don't want. I want to restrict the imageView within the boundaries of it's parent view. How to do that.
Here is the xml:
<FrameLayout
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:id="#+id/objContainer"
android:background="#android:color/holo_blue_bright" >
<ImageView
android:id="#+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/btn_default" />
</FrameLayout>
</RelativeLayout>
And code to handletouch event:
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
final float x = event.getRawX();
final float y = event.getRawY();
// Remember where we started
mLastTouchX = x;
mLastTouchY = y;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
case MotionEvent.ACTION_MOVE:
final float x1 = event.getRawX();
final float y1 = event.getRawY();
// Calculate the distance moved
final float dx = x1 - mLastTouchX;
final float dy = y1 - mLastTouchY;
// Move the object
mPosX += dx;
mPosY += dy;
view.setX(mPosX);
view.setY(mPosY);
// Remember this touch position for the next move event
mLastTouchX = x1;
mLastTouchY = y1;
// Invalidate to request a redraw
root.invalidate();
break;
}
return true;
}}
Inside of your overridden onTouch you need to check if the following move will keep the ImageView inside its container.
In other words you need to check if ImageView's rectangle will stay inside the parent after being moved by dx, dy.
Here's an example:
case MotionEvent.ACTION_MOVE:
...
// Calculate the distance moved
final float dx = x1 - mLastTouchX;
final float dy = y1 - mLastTouchY;
// Make sure we will still be the in parent's container
Rect parent = new Rect(0, 0, root.getWidth(), root.getHeight());
int newLeft = (int) (iv.getX() + dx),
newTop = (int) (iv.getY() + dy),
newRight = newLeft + iv.getWidth(),
newBottom = newTop + iv.getHeight();
if (!parent.contains(newLeft, newTop, newRight, newBottom)) {
Log.e(TAG, String.format("OOB # %d, %d - %d, %d",
newLeft, newTop, newRight, newBottom));
break;
}
...
Note also that you don't need to invalidate the container, as setX/setY invalidates the ImageView itself.
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.
Basically my question is: how to move a complete view around, instead of just moving the canvas? *I have a custom view and I want to move the whole thing not just the canvas.*
This is what I have tried, but I get a NullPointerException (the code is not compleate, I have put what I think is the most relevant part, also the parent of the custom view is a LinearLayout):
ResistorView class:
LinearLayout root;
public class ResistorView extends View{
public ResistorView(Context context){
super(context);
root = (LinearLayout)findViewById(R.id.main);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int X = (int) event.getRawX();
final int Y = (int) event.getRawY();
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
LinearLayout.LayoutParams lParams = (LinearLayout.LayoutParams) this.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:
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) this.getLayoutParams();
layoutParams.leftMargin = X - _xDelta;
layoutParams.topMargin = Y - _yDelta;
layoutParams.rightMargin = -250;
layoutParams.bottomMargin = -250;
this.setLayoutParams(layoutParams);
break;
}
root.invalidate(); //There is a NullPointerException on this line.
return true;
}
main layout:
<?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="vertical"
android:id="#+id/main">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<Button
android:id="#+id/bAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add RES" />
</LinearLayout>
I don't know what I am doing wrong, if someone can help I would really appreciated. Thanks.
Change
root = (LinearLayout)findViewById(R.id.main);
to
root = (LinearLayout)getParent();
You may even want to do this inside of onTouch instead and remove it from the constructor, something like:
if(root == null) {
root = (LinearLayout)getParent();
}
root.invalidate();
I suggest using FrameLayout and call myCustomView.setX(x) and myCustomView.setY(y)
x and y passed to methods are event rawX and rawY + deltaX and deltaY
ACTION_DOWN case
deltaX = v.x - event.rawX
deltaY = v.y - event.rawY
deltaX and deltaY are global variables
and in ACTION_MOVE case do this
v.x = event.rawX + deltaX
v.y = event.rawY + deltaY
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!