Exemple #1
0
		/// <summary>
		/// Scrolls the specified widget to the specified coordinates, except
		/// constrains the X scrolling position to the horizontal regions of
		/// the text that will be visible after scrolling to the specified
		/// Y position.
		/// </summary>
		/// <remarks>
		/// Scrolls the specified widget to the specified coordinates, except
		/// constrains the X scrolling position to the horizontal regions of
		/// the text that will be visible after scrolling to the specified
		/// Y position.
		/// </remarks>
		public static void scrollTo(android.widget.TextView widget, android.text.Layout layout
			, int x, int y)
		{
			int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(
				);
			int top = layout.getLineForVertical(y);
			int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding);
			int left = int.MaxValue;
			int right = 0;
			android.text.Layout.Alignment? a = layout.getParagraphAlignment(top);
			bool ltr = layout.getParagraphDirection(top) > 0;
			{
				for (int i = top; i <= bottom; i++)
				{
					left = (int)System.Math.Min(left, layout.getLineLeft(i));
					right = (int)System.Math.Max(right, layout.getLineRight(i));
				}
			}
			int hoizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight
				();
			int availableWidth = widget.getWidth() - hoizontalPadding;
			int actualWidth = right - left;
			if (actualWidth < availableWidth)
			{
				if (a == android.text.Layout.Alignment.ALIGN_CENTER)
				{
					x = left - ((availableWidth - actualWidth) / 2);
				}
				else
				{
					if ((ltr && (a == android.text.Layout.Alignment.ALIGN_OPPOSITE)) || (a == android.text.Layout.Alignment
						.ALIGN_RIGHT))
					{
						// align_opposite does NOT mean align_right, we need the paragraph
						// direction to resolve it to left or right
						x = left - (availableWidth - actualWidth);
					}
					else
					{
						x = left;
					}
				}
			}
			else
			{
				x = System.Math.Min(x, right - availableWidth);
				x = System.Math.Max(x, left);
			}
			widget.scrollTo(x, y);
		}
Exemple #2
0
		/// <summary>
		/// Returns an immutable bitmap from subset of the source bitmap,
		/// transformed by the optional matrix.
		/// </summary>
		/// <remarks>
		/// Returns an immutable bitmap from subset of the source bitmap,
		/// transformed by the optional matrix.  It is
		/// initialized with the same density as the original bitmap.
		/// </remarks>
		/// <param name="source">The bitmap we are subsetting</param>
		/// <param name="x">The x coordinate of the first pixel in source</param>
		/// <param name="y">The y coordinate of the first pixel in source</param>
		/// <param name="width">The number of pixels in each row</param>
		/// <param name="height">The number of rows</param>
		/// <param name="m">Optional matrix to be applied to the pixels</param>
		/// <param name="filter">
		/// true if the source should be filtered.
		/// Only applies if the matrix contains more than just
		/// translation.
		/// </param>
		/// <returns>A bitmap that represents the specified subset of source</returns>
		/// <exception cref="System.ArgumentException">
		/// if the x, y, width, height values are
		/// outside of the dimensions of the source bitmap.
		/// </exception>
		public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap source
			, int x, int y, int width, int height, android.graphics.Matrix m, bool filter)
		{
			checkXYSign(x, y);
			checkWidthHeight(width, height);
			if (x + width > source.getWidth())
			{
				throw new System.ArgumentException("x + width must be <= bitmap.width()");
			}
			if (y + height > source.getHeight())
			{
				throw new System.ArgumentException("y + height must be <= bitmap.height()");
			}
			// check if we can just return our argument unchanged
			if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() && height
				 == source.getHeight() && (m == null || m.isIdentity()))
			{
				return source;
			}
			int neww = width;
			int newh = height;
			android.graphics.Canvas canvas = new android.graphics.Canvas();
			android.graphics.Bitmap bitmap;
			android.graphics.Paint paint;
			android.graphics.Rect srcR = new android.graphics.Rect(x, y, x + width, y + height
				);
			android.graphics.RectF dstR = new android.graphics.RectF(0, 0, width, height);
			android.graphics.Bitmap.Config newConfig = android.graphics.Bitmap.Config.ARGB_8888;
			android.graphics.Bitmap.Config config = source.getConfig();
			// GIF files generate null configs, assume ARGB_8888
			if (config != null)
			{
				switch (config)
				{
					case android.graphics.Bitmap.Config.RGB_565:
					{
						newConfig = android.graphics.Bitmap.Config.RGB_565;
						break;
					}

					case android.graphics.Bitmap.Config.ALPHA_8:
					{
						newConfig = android.graphics.Bitmap.Config.ALPHA_8;
						break;
					}

					case android.graphics.Bitmap.Config.ARGB_4444:
					case android.graphics.Bitmap.Config.ARGB_8888:
					default:
					{
						//noinspection deprecation
						newConfig = android.graphics.Bitmap.Config.ARGB_8888;
						break;
					}
				}
			}
			if (m == null || m.isIdentity())
			{
				bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
				paint = null;
			}
			else
			{
				// not needed
				bool transformed = !m.rectStaysRect();
				android.graphics.RectF deviceR = new android.graphics.RectF();
				m.mapRect(deviceR, dstR);
				neww = Sharpen.Util.Round(deviceR.width());
				newh = Sharpen.Util.Round(deviceR.height());
				bitmap = createBitmap(neww, newh, transformed ? android.graphics.Bitmap.Config.ARGB_8888
					 : newConfig, transformed || source.hasAlpha());
				canvas.translate(-deviceR.left, -deviceR.top);
				canvas.concat(m);
				paint = new android.graphics.Paint();
				paint.setFilterBitmap(filter);
				if (transformed)
				{
					paint.setAntiAlias(true);
				}
			}
			// The new bitmap was created from a known bitmap source so assume that
			// they use the same density
			bitmap.mDensity = source.mDensity;
			canvas.setBitmap(bitmap);
			canvas.drawBitmap(source, srcR, dstR, paint);
			canvas.setBitmap(null);
			return bitmap;
		}
Exemple #3
0
		/// <summary>Returns an immutable bitmap from the source bitmap.</summary>
		/// <remarks>
		/// Returns an immutable bitmap from the source bitmap. The new bitmap may
		/// be the same object as source, or a copy may have been made.  It is
		/// initialized with the same density as the original bitmap.
		/// </remarks>
		public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap src)
		{
			return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
		}
Exemple #4
0
		/// <summary>Creates a new bitmap, scaled from an existing bitmap.</summary>
		/// <remarks>Creates a new bitmap, scaled from an existing bitmap.</remarks>
		/// <param name="src">The source bitmap.</param>
		/// <param name="dstWidth">The new bitmap's desired width.</param>
		/// <param name="dstHeight">The new bitmap's desired height.</param>
		/// <param name="filter">true if the source should be filtered.</param>
		/// <returns>the new scaled bitmap.</returns>
		public static android.graphics.Bitmap createScaledBitmap(android.graphics.Bitmap 
			src, int dstWidth, int dstHeight, bool filter)
		{
			android.graphics.Matrix m;
			lock (typeof(android.graphics.Bitmap))
			{
				// small pool of just 1 matrix
				m = sScaleMatrix;
				sScaleMatrix = null;
			}
			if (m == null)
			{
				m = new android.graphics.Matrix();
			}
			int width = src.getWidth();
			int height = src.getHeight();
			float sx = dstWidth / (float)width;
			float sy = dstHeight / (float)height;
			m.setScale(sx, sy);
			android.graphics.Bitmap b = android.graphics.Bitmap.createBitmap(src, 0, 0, width
				, height, m, filter);
			lock (typeof(android.graphics.Bitmap))
			{
				// do we need to check for null? why not just assign everytime?
				if (sScaleMatrix == null)
				{
					sScaleMatrix = m;
				}
			}
			return b;
		}
Exemple #5
0
		private static android.graphics.Bitmap finishDecode(android.graphics.Bitmap bm, android.graphics.Rect
			 outPadding, android.graphics.BitmapFactory.Options opts)
		{
			if (bm == null || opts == null)
			{
				return bm;
			}
			int density = opts.inDensity;
			if (density == 0)
			{
				return bm;
			}
			bm.setDensity(density);
			int targetDensity = opts.inTargetDensity;
			if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity)
			{
				return bm;
			}
			byte[] np = bm.getNinePatchChunk();
			bool isNinePatch = np != null && android.graphics.NinePatch.isNinePatchChunk(np);
			if (opts.inScaled || isNinePatch)
			{
				float scale = targetDensity / (float)density;
				// TODO: This is very inefficient and should be done in native by Skia
				android.graphics.Bitmap oldBitmap = bm;
				bm = android.graphics.Bitmap.createScaledBitmap(oldBitmap, (int)(bm.getWidth() * 
					scale + 0.5f), (int)(bm.getHeight() * scale + 0.5f), true);
				oldBitmap.recycle();
				if (isNinePatch)
				{
					np = nativeScaleNinePatch(np, scale, outPadding);
					bm.setNinePatchChunk(np);
				}
				bm.setDensity(targetDensity);
			}
			return bm;
		}
Exemple #6
0
		/// <summary>
		/// Returns the maximum height that is available for the popup to be
		/// completely shown, optionally ignoring any bottom decorations such as
		/// the input method.
		/// </summary>
		/// <remarks>
		/// Returns the maximum height that is available for the popup to be
		/// completely shown, optionally ignoring any bottom decorations such as
		/// the input method. It is recommended that this height be the maximum for
		/// the popup's height, otherwise it is possible that the popup will be
		/// clipped.
		/// </remarks>
		/// <param name="anchor">The view on which the popup window must be anchored.</param>
		/// <param name="yOffset">y offset from the view's bottom edge</param>
		/// <param name="ignoreBottomDecorations">
		/// if true, the height returned will be
		/// all the way to the bottom of the display, ignoring any
		/// bottom decorations
		/// </param>
		/// <returns>
		/// The maximum available height for the popup to be completely
		/// shown.
		/// </returns>
		/// <hide>Pending API council approval.</hide>
		public virtual int getMaxAvailableHeight(android.view.View anchor, int yOffset, bool
			 ignoreBottomDecorations)
		{
			android.graphics.Rect displayFrame = new android.graphics.Rect();
			anchor.getWindowVisibleDisplayFrame(displayFrame);
			int[] anchorPos = mDrawingLocation;
			anchor.getLocationOnScreen(anchorPos);
			int bottomEdge = displayFrame.bottom;
			if (ignoreBottomDecorations)
			{
				android.content.res.Resources res = anchor.getContext().getResources();
				bottomEdge = res.getDisplayMetrics().heightPixels;
			}
			int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
			int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
			// anchorPos[1] is distance from anchor to top of screen
			int returnedHeight = System.Math.Max(distanceToBottom, distanceToTop);
			if (mBackground != null)
			{
				mBackground.getPadding(mTempRect);
				returnedHeight -= mTempRect.top + mTempRect.bottom;
			}
			return returnedHeight;
		}
Exemple #7
0
		/// <summary><p>Positions the popup window on screen.</summary>
		/// <remarks>
		/// <p>Positions the popup window on screen. When the popup window is too
		/// tall to fit under the anchor, a parent scroll view is seeked and scrolled
		/// up to reclaim space. If scrolling is not possible or not enough, the
		/// popup window gets moved on top of the anchor.</p>
		/// <p>The height must have been set on the layout parameters prior to
		/// calling this method.</p>
		/// </remarks>
		/// <param name="anchor">the view on which the popup window must be anchored</param>
		/// <param name="p">the layout parameters used to display the drop down</param>
		/// <returns>true if the popup is translated upwards to fit on screen</returns>
		private bool findDropDownPosition(android.view.View anchor, android.view.WindowManagerClass
			.LayoutParams p, int xoff, int yoff)
		{
			int anchorHeight = anchor.getHeight();
			anchor.getLocationInWindow(mDrawingLocation);
			p.x = mDrawingLocation[0] + xoff;
			p.y = mDrawingLocation[1] + anchorHeight + yoff;
			bool onTop = false;
			p.gravity = android.view.Gravity.LEFT | android.view.Gravity.TOP;
			anchor.getLocationOnScreen(mScreenLocation);
			android.graphics.Rect displayFrame = new android.graphics.Rect();
			anchor.getWindowVisibleDisplayFrame(displayFrame);
			int screenY = mScreenLocation[1] + anchorHeight + yoff;
			android.view.View root = anchor.getRootView();
			if (screenY + mPopupHeight > displayFrame.bottom || p.x + mPopupWidth - root.getWidth
				() > 0)
			{
				// if the drop down disappears at the bottom of the screen. we try to
				// scroll a parent scrollview or move the drop down back up on top of
				// the edit box
				if (mAllowScrollingAnchorParent)
				{
					int scrollX = anchor.getScrollX();
					int scrollY = anchor.getScrollY();
					android.graphics.Rect r = new android.graphics.Rect(scrollX, scrollY, scrollX + mPopupWidth
						 + xoff, scrollY + mPopupHeight + anchor.getHeight() + yoff);
					anchor.requestRectangleOnScreen(r, true);
				}
				// now we re-evaluate the space available, and decide from that
				// whether the pop-up will go above or below the anchor.
				anchor.getLocationInWindow(mDrawingLocation);
				p.x = mDrawingLocation[0] + xoff;
				p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
				// determine whether there is more space above or below the anchor
				anchor.getLocationOnScreen(mScreenLocation);
				onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) < 
					(mScreenLocation[1] - yoff - displayFrame.top);
				if (onTop)
				{
					p.gravity = android.view.Gravity.LEFT | android.view.Gravity.BOTTOM;
					p.y = root.getHeight() - mDrawingLocation[1] + yoff;
				}
				else
				{
					p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
				}
			}
			if (mClipToScreen)
			{
				int displayFrameWidth = displayFrame.right - displayFrame.left;
				int right = p.x + p.width;
				if (right > displayFrameWidth)
				{
					p.x -= right - displayFrameWidth;
				}
				if (p.x < displayFrame.left)
				{
					p.x = displayFrame.left;
					p.width = System.Math.Min(p.width, displayFrameWidth);
				}
				if (onTop)
				{
					int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
					if (popupTop < 0)
					{
						p.y += popupTop;
					}
				}
				else
				{
					p.y = System.Math.Max(p.y, displayFrame.top);
				}
			}
			p.gravity |= android.view.Gravity.DISPLAY_CLIP_VERTICAL;
			return onTop;
		}
Exemple #8
0
		/// <summary>Draw the picture, stretched to fit into the dst rectangle.</summary>
		/// <remarks>Draw the picture, stretched to fit into the dst rectangle.</remarks>
		public virtual void drawPicture(android.graphics.Picture picture, android.graphics.Rect
			 dst)
		{
			save();
			translate(dst.left, dst.top);
			if (picture.getWidth() > 0 && picture.getHeight() > 0)
			{
				scale((float)dst.width() / picture.getWidth(), (float)dst.height() / picture.getHeight
					());
			}
			drawPicture(picture);
			restore();
		}
Exemple #9
0
		/// <summary>Figure out vertical placement based on mGravity</summary>
		/// <param name="child">Child to place</param>
		/// <returns>Where the top of the child should be</returns>
		private int calculateTop(android.view.View child, bool duringLayout)
		{
			int myHeight = duringLayout ? getMeasuredHeight() : getHeight();
			int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight();
			int childTop = 0;
			switch (mGravity)
			{
				case android.view.Gravity.TOP:
				{
					childTop = mSpinnerPadding.top;
					break;
				}

				case android.view.Gravity.CENTER_VERTICAL:
				{
					int availableSpace = myHeight - mSpinnerPadding.bottom - mSpinnerPadding.top - childHeight;
					childTop = mSpinnerPadding.top + (availableSpace / 2);
					break;
				}

				case android.view.Gravity.BOTTOM:
				{
					childTop = myHeight - mSpinnerPadding.bottom - childHeight;
					break;
				}
			}
			return childTop;
		}
		private int getInnerHeight(android.widget.TextView widget)
		{
			return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom
				();
		}