All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.qozix.layouts.AnchorLayout Maven / Gradle / Ivy

Go to download

The TileView widget is a subclass of ViewGroup that provides a mechanism to asynchronously display tile-based images, with additional functionality for 2D dragging, flinging, pinch or double-tap to zoom, adding overlaying Views (markers), built-in Hot Spot support, dynamic path drawing, multiple levels of detail, and support for any relative positioning or coordinate system.

The newest version!
package com.qozix.layouts;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;

/**
 * The AnchorLayout positions it's children using absolute pixel values,
 * offset by anchors.  An anchor exists on each axis (x and y), and is
 * determined by multiplying the relevant dimension of the child (width for x,
 * height for y) by a float.  This float can be supplied to each child via
 * LayoutParams, or to the AnchorLayout ViewGroup directly.  If a child's
 * LayoutParams are not specified (null), then it will be positioned using
 * the Layout's anchor values.
 * 
 * For example, passing an -0.5f anchorX and -1.0f anchorY will position the
 * view entirely above, and centered horizontally, relative to the pixel
 * coordinates supplied.
 * 
 * This is useful for positioning elements as indicators for another view,
 * or graphical feature.  Tooltips, map markers, instructional elements, etc
 * could benefit from anchored layouts.
 */

public class AnchorLayout extends ViewGroup {

	protected float anchorX = 0f;
	protected float anchorY = 0f;

	public AnchorLayout( Context context ) {
		super( context );
	}

	/**
	 * Sets the anchor values used by this ViewGroup if it's children do not
	 * have anchor values supplied directly (via LayoutParams)
	 * @param aX (float) x-axis anchor value (offset computed by multiplying this value by the child's width
	 * @param aY (float) y-axis anchor value (offset computed by multiplying this value by the child's height
	 */
	public void setAnchors( float aX, float aY ) {
		anchorX = aX;
		anchorY = aY;
		requestLayout();
	}

	@Override
	protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) {

		measureChildren( widthMeasureSpec, heightMeasureSpec );

		int width = 0;
		int height = 0;

		int count = getChildCount();
		for ( int i = 0; i < count; i++ ) {
			View child = getChildAt( i );
			if ( child.getVisibility() != GONE ) {
				AnchorLayout.LayoutParams lp = (AnchorLayout.LayoutParams) child.getLayoutParams();
				// get anchor offsets
				float aX = ( lp.anchorX == null ) ? anchorX : lp.anchorX;
				float aY = ( lp.anchorY == null ) ? anchorY : lp.anchorY;
				// offset dimensions by anchor values
				int computedWidth = (int) ( child.getMeasuredWidth() * aX );
				int computedHeight = (int) ( child.getMeasuredHeight() * aY );
				// add computed dimensions to actual position
				int right = lp.x + computedWidth;
				int bottom = lp.y + computedHeight;
				// if it's larger, use that
				width = Math.max( width, right );
				height = Math.max( height, bottom );
			}
		}

		height = Math.max( height, getSuggestedMinimumHeight() );
		width = Math.max( width, getSuggestedMinimumWidth() );
		width = resolveSize( width, widthMeasureSpec );
		height = resolveSize( height, heightMeasureSpec );
		setMeasuredDimension( width, height );

	}

	@Override
	protected void onLayout( boolean changed, int l, int t, int r, int b ) {
		int count = getChildCount();
		for ( int i = 0; i < count; i++ ) {
			View child = getChildAt( i );
			if ( child.getVisibility() != GONE ) {
				LayoutParams lp = (LayoutParams) child.getLayoutParams();
				// get sizes
				int w = child.getMeasuredWidth();
				int h = child.getMeasuredHeight();
				// user child's layout params anchor position if set, otherwise
				// default to anchor position of layout
				float aX = ( lp.anchorX == null ) ? anchorX : lp.anchorX;
				float aY = ( lp.anchorY == null ) ? anchorY : lp.anchorY;
				// apply anchor offset to position
				int x = lp.x + (int) ( w * aX );
				int y = lp.y + (int) ( h * aY );
				// set it
				child.layout( x, y, x + w, y + h );
			}
		}
	}

	@Override
	protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
		return new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0 );
	}

	@Override
	protected boolean checkLayoutParams( ViewGroup.LayoutParams p ) {
		return p instanceof AnchorLayout.LayoutParams;
	}

	@Override
	protected ViewGroup.LayoutParams generateLayoutParams( ViewGroup.LayoutParams p ) {
		return new LayoutParams( p );
	}

	/**
	 * Per-child layout information associated with AnchorLayout.
	 */
	public static class LayoutParams extends ViewGroup.LayoutParams {

		/**
		 * The absolute left position of the child in pixels
		 */
		public int x = 0;
		/**
		 * The absolute right position of the child in pixels
		 */
		public int y = 0;
		/**
		 * Float value to determine the child's horizontal offset. This float is multiplied by the child's width.  If null, the containing AnchorLayout's anchor values will be used.
		 */
		public Float anchorX = null;
		/**
		 * Float value to determine the child's vertical offset. This float is multiplied by the child's height.  If null, the containing AnchorLayout's anchor values will be used.
		 */
		public Float anchorY = null;

		/**
		 * Copy constructor
		 * @param source (LayoutParams) LayoutParams instance to copy properties from
		 */
		public LayoutParams( ViewGroup.LayoutParams source ) {
			super( source );
		}

		/**
		 * Creates a new set of layout parameters with the specified values.
		 * @param width (int) Information about how wide the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 * @param height (int) Information about how tall the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 */
		public LayoutParams( int width, int height ) {
			super( width, height );
		}

		/**
		 * Creates a new set of layout parameters with the specified values.
		 * @param width (int) Information about how wide the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 * @param height (int) Information about how tall the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 * @param left (int) Sets the absolute x value of the view's position in pixels
		 * @param top (int) Sets the absolute y value of the view's position in pixels
		 */
		public LayoutParams( int width, int height, int left, int top ) {
			super( width, height );
			x = left;
			y = top;
		}
		
		/**
		 * Creates a new set of layout parameters with the specified values.
		 * @param width (int) Information about how wide the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 * @param height (int) Information about how tall the view wants to be.  This should generally be WRAP_CONTENT or a fixed value.
		 * @param left (int) Sets the absolute x value of the view's position in pixels
		 * @param top (int) Sets the absolute y value of the view's position in pixels
		 * @param aX (float) Sets the relative horizontal offset of the view (multiplied by the view's width)
		 * @param aY (float) Sets the relative vertical offset of the view (multiplied by the view's height)
		 */
		public LayoutParams( int width, int height, int left, int top, float aX, float aY ) {
			super( width, height );
			x = left;
			y = top;
			anchorX = aX;
			anchorY = aY;
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy