Tuesday, 2 April 2013

Circular Menu Part-1

Main Activity


public class TestMenuActivity extends Activity {
CircleView cView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

int numberOfElements = 11;
View[] elems = new View[numberOfElements];

EditText tv = new EditText(this);
tv.setText("Some text");
tv.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
elems[0] = tv;

for (int i = 1; i < numberOfElements - 1; i++) {
Button newButton = new Button(this);
newButton.setText("Button   " + i);
newButton.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
elems[i] = newButton;
}

Spinner sp = new Spinner(this);
sp.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
elems[numberOfElements - 1] = sp;

cView = new CircleView(this, 115, elems);
setContentView(cView);
}
}


How To Create Circle View (Dynamically...)


public class CircleView extends RelativeLayout {
static final int centerId = 111;
private final int radius;

private RelativeLayout.LayoutParams createNewRelativeLayoutParams() {
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.ABOVE, centerId);
lp.addRule(RIGHT_OF, centerId);
return lp;
}

private View prepareElementForCircle(View elem, int distX, int distY) {
RelativeLayout.LayoutParams lp = createNewRelativeLayoutParams();

elem.measure(0, 0);
int deltaX = elem.getMeasuredWidth() / 2;
int deltaY = elem.getMeasuredHeight() / 2;
lp.setMargins(distX - deltaX, 0, 0, radius - distY - deltaY);
elem.setLayoutParams(lp);
return elem;
}

public CircleView(Context context, int radius, View[] elements) {
super(context);
this.radius = radius;

RelativeLayout.LayoutParams lpView = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
this.setLayoutParams(lpView);

View center = new View(context);
center.setId(centerId);
RelativeLayout.LayoutParams lpcenter = new RelativeLayout.LayoutParams(
0, 0);
lpcenter.addRule(CENTER_HORIZONTAL);
lpcenter.addRule(CENTER_VERTICAL);
center.setLayoutParams(lpcenter);
this.addView(center);

this.addView(prepareElementForCircle(elements[0], 0, 0));
if (elements.length % 2 == 0) {
this.addView(prepareElementForCircle(elements[elements.length / 2],
0, 2 * radius));
}
if (elements.length > 2) {
for (int i = 1; i <= (elements.length - 1) / 2; i++) {
int y = i * 4 * radius / elements.length;
int x = (int) Math.sqrt(Math.pow(radius, 2)
- Math.pow((radius - y), 2));
this.addView(prepareElementForCircle(elements[i], x, y));
this.addView(prepareElementForCircle(elements[elements.length
- i], -x, y));
}
}
}

}


Monday, 1 April 2013

Google to Launch an Android-powered Smartwatch






























We are hearing a lot of news of Smart watch, that Apple and Samsung wants to launch Smart Watch now Google also wants to Jump in launch Android-powered Smartwatch. Google owns a patent of Dual-screen smart watch since 2011, and now Android team is working on that watch its possibiity that Googlesmart watch hit the market before Google Glass.



A smartwatch boom seems to be going on. Besides smaller companies debuting new wrist technology, the tech giants are also grabbing for a piece of the pie. Google is the newest company to supposedly be stepping into the watch world. According to The Financial Times, Google’s smartwatch is allegedly being developed by the company’s Android unit rather than its X Lab.
This is telling because it means that, unlike Google Glass, the company may be looking to get a consumer product out to users on a speedier timeline. According to The Financial Times, Google filed a patent application for a “smart watch” in 2011. Apparently, the patent has a dual-screened display and a interactive user interface. Over the past couple of weeks Apple has been rumored to be coming out with a smartwatch and Samsung has confirmed it’s working on one. Of course, none of these mammoth companies are breaking new ground. A lot of smartwatches, fitness bands, or some hybrid of the two have already been unveiled, including the long-awaited Pebble wristwatch and the 007-inspired Martian.

Sunday, 31 March 2013

The role of Transformation Matrices in Animation


The mechanics of animation of are quite simple. Take any scene and if you repaint it quick while some aspect of that scene is changing you get the impression that something is moving smoothly although the repaint is happening only with a certain frequency which is typically 24 or 12 frames per second.
what changes at every redraw may be color, position, orientation, or size or any combination of these. If you want to take a view or a scene or a picture and want to move that scene to the right by a few pixels, you will typically define a transformation matrix and then apply a matrix multiplication or transformation on every pixel of the scene to get the new location. So each tranformation is identified by a certain matrix.
If you start with an identity matrix and then apply each transformation to it then you will get a final matrix that you can apply just one time to transform the view. By changing these matrices in a gradual manner in a time loop you will accomplish animation. Let's spend a little bit more time and understand the matrix api before going further.
You can get an identity matrix by doing

import android.graphics.Matrix;
Matrix matrix = new Matrix();
To achieve rotation you can do

matrix.setRotate(degrees)
This method will rotate the view around origin by those many degrees in a 2D space. Some other methods are

matrix.setScale(x,y);
matrix.setTranslate(x,y);
matrix.setSkew(x,y); 
As you call these methods to arrive at a desired matrix be aware of the "set" semantics. "set" semantics works like a "setting" a variable which means "replace" the current value with the new value. All of these methods, if you follow the java source code of android eventually resolve to some c++ code from a core google graphics library called "skia". You can explore the source code online at

http://android.git.kernel.org/
"git" is a source code control system used by the android open source project. You can learn more about "git" SCM here at

http://git.or.cz/
Now back to understanding of the "set" semantics on these graphics matrices. Let us take a look at the source code for "setScale":

void SkMatrix::setScale(SkScalar sx, SkScalar sy) {
    fMat[kMScaleX] = sx;
    fMat[kMScaleY] = sy;
    fMat[kMPersp2] = kMatrix22Elem;

    fMat[kMTransX] = fMat[kMTransY] =
    fMat[kMSkewX]  = fMat[kMSkewY] = 
    fMat[kMPersp0] = fMat[kMPersp1] = 0;

    this->setTypeMask(kScale_Mask | kRectStaysRect_Mask);
}
The scale function replaces all previous scaling values and pretty much resets the matrix and sets the scale. So if you have done anything else to the matrix all that is gone. Let us take a look at the "setTranslate" to see if that is any different.

void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
    if (SkScalarAs2sCompliment(dx) | SkScalarAs2sCompliment(dy)) {
        fMat[kMTransX] = dx;
        fMat[kMTransY] = dy;

        fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1;
        fMat[kMSkewX]  = fMat[kMSkewY] = 
        fMat[kMPersp0] = fMat[kMPersp1] = 0;
        fMat[kMPersp2] = kMatrix22Elem;

        this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
    } else {
        this->reset();
    }
}
Basically sets the scale back to 1 and sets the translations replacing everything before.
So what do you do if you want to apply multiple transformations in a tow. Matrix class provides a set of "pre*" and "post*" functions for each of the "set*" fucnctions. Let us take a look at the source code for "preScale"

bool SkMatrix::preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
    SkMatrix    m;
    m.setScale(sx, sy, px, py);
    return this->preConcat(m);
}

bool SkMatrix::preConcat(const SkMatrix& mat) {
    return this->setConcat(*this, mat);
}

bool SkMatrix::postConcat(const SkMatrix& mat) {
    return this->setConcat(mat, *this);
}
Essentially "preScale" creates a brand new matrix with the given scale and then multiplies that matrix with the current matrix and replaces the current matrix with the resultant matrix. When matrices are multiplied the order is important. So if we do

m.setScale(..) = rm1
m.preScale(..) = m2 x rm1 = rm3
m.postScale(..) = rm3 x m4 = rm5
I could have acheived the same with

m1.setScale() = m1
m2.setScale() = m2
m3.setScale() = m3

m1.setConcat(m2,m1); // rm3
m1.setConcat(m1,m3); // rm5
You can concat
If "m1" was an identity matrix then the following two would be equal as well

m1.postTranslate(); // take it to the origin
m1.postScale(); //scale it
m1.postTranslate();// take it back to the center

m2.setScale();
m2.preTranslate();
m2.postTranslate();

Here is some more sample code demonstrating matrix equivalence based on the order of operations on that matrix

public class TestMatrix
{
public static void test(SomeActivity a)
{
test1(a);
test2(a);
test3(a);
}
public static void test1(SomeActivity a)
{
Matrix m1 = new Matrix();
m1.setScale(2, 2);
m1.preScale(2, 2);
m1.postScale(2, 2);
Matrix m2 = new Matrix();
m2.postScale(2, 2);
m2.postScale(2, 2);
m2.postScale(2, 2);
assertL("test1",a,m1,m2,"m1 and m2 will be same");
}
public static void test2(SomeActivity a)
{
Matrix m1 = new Matrix();
m1.setScale(2, 2);
m1.preTranslate(-2, -2);
m1.postTranslate(2, 2);
Matrix m2 = new Matrix();
m2.postTranslate(-2, -2);
m2.postScale(2, 2);
m2.postTranslate(2, 2);
assertL("test2",a,m1,m2,"m1 and m2 will be the same");
}
public static void test3(SomeActivity a)
{
Matrix m1 = new Matrix();
m1.setScale(2, 2);
m1.preTranslate(-2, -2);
m1.postTranslate(2, 2);
Matrix m2 = new Matrix();
m2.preTranslate(-2, -2);
m2.postTranslate(2, 2);
m2.setScale(2, 2);
assertL("test4",a,m1,m2,"m1 and m2 will not be the same");
Matrix m3 = new Matrix();
m3.setScale(2, 2);
assertL("test3",a,m2,m3,"m2 and m3 will be the same");
}
private static void assertL(String testName
, SomeActivity a
, Matrix m1
, Matrix m2
, String assertText)
{
if (m1.equals(m2))
{
a.appendText("\n" + testName + ": m1 is same as m2");
}
else
{
a.appendText("\n" + testName + ": m1 is NOT same as m2");
}
}
}
view raw TestMatrix.java hosted with ❤ by GitHub
In summary all the "pre*" and "post*" methods are mere shortcuts to "setConcat" against itself.

preTranslate(m) -> setConcat(m x self) 
preRotate(m) -> setConcat(m x self)
preScale(m) -> setConcat(m x self)
preSkew(m) -> setConcat(m x self)

postTranslate(m) -> setConcat (self x m)
postRotate(m) -> setConcat (self x m)
postScale(m) -> setConcat (self x m)
postSkew(m) -> setConcat (self x m)

Introduction To Animation In Android

Android supports two kinds of animation. 
  • One is called "Tweened Animation". 
  • The second one is called "Frame by Frame" animation. 
"Tween" is a short for "in-between" borrowed from traditional animators. Inbetweens are drawings that simulate motion between key frames. There may be 24 inbetweens between two key frames or there could be 12 between two key frames. The former case is called "on ones" and the later ones are called "on twos".

In Android here is how "tweening" works. You start with a view. This view can be any view including a view group with any set of complex composed graphical objects. When tweening animation is attached to this view, the animation gets a call back at regular intervals to change any aspect of the tranformation matrix that would be used to render the view.

Moving an object or scaling an object, or changing the shade of an object can all be represented as a set of matrix transformations. By changing this matrix in the call back of the animation you will render the object at a different place with a different scale or a diferent color.


So at a general level, tweening animation is acomplished by changing the properties of a view at various time intervals during the alloted time of an animation.


Android supports the following types of "tween" animations

  • AlphaAnimation: Changing Transparency of an object
  • RotateAnimation: Rotating an object
  • ScaleAnimation: Scale an object
  • TranslateAnimation: Move an object


In Android frame by frame animation a series of drawable resources are loaded one after the other. The class AnimationDrawable is responsible for frame by frame animation. Each frame in this animation is a drawable resource.


As you get deeper into Android animation you will see that the distinction is not so clearcut where you can mix both concepts by essentially redrawing the canvas one way or the other.




Saturday, 30 March 2013

ViewPager and PagerTabStrip


Note: Require "android-support-v4.jar" and its size greater than 3mb.


/* main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/background" >
<android.support.v4.view.PagerTabStrip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</android.support.v4.view.ViewPager>
*/
//ViewPager Adapter
public class ViewPagerAdapter extends PagerAdapter {
// ----------------------------------------------------------------
private Gallery gallery_disc, gallery_fest, gallery_combo;
private ImageView selectedImageView;
private ImageView leftArrowImageView;
private ImageView rightArrowImageView;
private int discPos, festPos, comboPos = 0;
private List<String> drawable, d1, d2, d3;
private GalleryImageAdapter disc_adapter, fest_adapter, combo_adapter;
TextView tvOfferName_disc, tvDesc_disc, tvItems_disc, tvDiscount_disc;
TextView tvOfferName_fest, tvDesc_fest, tvItems_fest, tvDiscount_fest;
TextView tvOfferName_combo, tvDesc_combo, tvItems_combo, tvDiscount_combo;
String discOffer[][];
String comboOffer[][];
String festOffer[][];
String temp = "% Discount on Following Items:";
ProgressDialog pd;
// --------------------------------------
private static String[] titles = new String[] { "Sport", "Music",
"Games" };
private final Context context;
private int[] scrollPosition = new int[titles.length];
public ViewPagerAdapter(Context context) {
this.context = context;
for (int i = 0; i < titles.length; i++) {
scrollPosition[i] = 0;
}
}
@Override
public String getPageTitle(int position) {
return titles[position];
}
@Override
public int getCount() {
return titles.length;
}
@Override
public Object instantiateItem(View pager, final int position) {
//Instantiate your all controls here
LinearLayout llmain=new LinearLayout(context);
((ViewPager) pager).addView(llmain, 0);
return llmain;
}
@Override
public void destroyItem(View pager, int position, Object view) {
((ViewPager) pager).removeView((LinearLayout) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void finishUpdate(View view) {
}
@Override
public void restoreState(Parcelable p, ClassLoader c) {
if (p instanceof ScrollState) {
scrollPosition = ((ScrollState) p).getScrollPos();
}
}
@Override
public Parcelable saveState() {
return new ScrollState(scrollPosition);
}
@Override
public void startUpdate(View view) {
}
}
//To Maintain Scroll State after each Swipe
public class ScrollState implements Parcelable
{
private int[] scrollPos;
public static Parcelable.Creator<ScrollState> CREATOR = new Parcelable.Creator<ScrollState>()
{
@Override
public ScrollState createFromParcel( Parcel source )
{
int size = source.readInt();
int[] scrollPos = new int[ size ];
source.readIntArray( scrollPos );
return new ScrollState( scrollPos );
}
@Override
public ScrollState[] newArray( int size )
{
return new ScrollState[ size ];
}
};
public ScrollState( int[] scrollPos )
{
this.scrollPos = scrollPos;
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel( Parcel dest, int flags )
{
dest.writeInt( scrollPos.length );
dest.writeIntArray( scrollPos );
}
public int[] getScrollPos()
{
return scrollPos;
}
}

Create Quick Action Menu






//Main Activity
public class QuickMenuActivity extends Activity {
/** Called when the activity is first created. */
private static final int ID_UP = 1;
private static final int ID_DOWN = 2;
private static final int ID_SEARCH = 3;
private static final int ID_INFO = 4;
private static final int ID_ERASE = 5;
private static final int ID_OK = 6;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ActionItem nextItem = new ActionItem(ID_DOWN, "Next", getResources()
.getDrawable(R.drawable.menu_down_arrow));
ActionItem prevItem = new ActionItem(ID_UP, "Prev", getResources()
.getDrawable(R.drawable.menu_up_arrow));
ActionItem searchItem = new ActionItem(ID_SEARCH, "Find",
getResources().getDrawable(R.drawable.menu_search));
ActionItem infoItem = new ActionItem(ID_INFO, "Info", getResources()
.getDrawable(R.drawable.menu_info));
ActionItem eraseItem = new ActionItem(ID_ERASE, "Clear", getResources()
.getDrawable(R.drawable.menu_eraser));
ActionItem okItem = new ActionItem(ID_OK, "OK", getResources()
.getDrawable(R.drawable.menu_ok));
// use setSticky(true) to disable QuickAction dialog being dismissed
// after an item is clicked
prevItem.setSticky(true);
nextItem.setSticky(true);
// create QuickAction. Use QuickAction.VERTICAL or
// QuickAction.HORIZONTAL param to define layout
// orientation
final QuickAction quickAction = new QuickAction(this,
QuickAction.VERTICAL);
// add action items into QuickAction
quickAction.addActionItem(nextItem);
quickAction.addActionItem(prevItem);
quickAction.addActionItem(searchItem);
quickAction.addActionItem(infoItem);
quickAction.addActionItem(eraseItem);
quickAction.addActionItem(okItem);
// Set listener for action item clicked
quickAction
.setOnActionItemClickListener(new QuickAction.OnActionItemClickListener() {
@Override
public void onItemClick(QuickAction source, int pos,
int actionId) {
ActionItem actionItem = quickAction.getActionItem(pos);
// here we can filter which action item was clicked with
// pos or actionId parameter
if (actionId == ID_SEARCH) {
Toast.makeText(getApplicationContext(),
"Let's do some search action",
Toast.LENGTH_SHORT).show();
} else if (actionId == ID_INFO) {
Toast.makeText(getApplicationContext(),
"I have no info this time",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),
actionItem.getTitle() + " selected",
Toast.LENGTH_SHORT).show();
}
}
});
// set listnener for on dismiss event, this listener will be called only
// if QuickAction dialog was dismissed
// by clicking the area outside the dialog.
quickAction.setOnDismissListener(new QuickAction.OnDismissListener() {
@Override
public void onDismiss() {
Toast.makeText(getApplicationContext(), "Dismissed",
Toast.LENGTH_SHORT).show();
}
});
// show on btn1
Button btn1 = (Button) this.findViewById(R.id.btn1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
quickAction.show(v);
}
});
Button btn2 = (Button) this.findViewById(R.id.btn2);
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
quickAction.show(v);
}
});
Button btn3 = (Button) this.findViewById(R.id.btn3);
btn3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
quickAction.show(v);
quickAction.setAnimStyle(QuickAction.ANIM_REFLECT);
}
});
}
}
//Popup Window Open and Dismiss
/**
* QuickAction dialog, shows action list as icon and text like the one in Gallery3D app. Currently supports vertical
* and horizontal layout.
*
*
*/
public class QuickAction extends PopupWindows implements OnDismissListener {
private View mRootView;
private ImageView mArrowUp;
private ImageView mArrowDown;
private LayoutInflater mInflater;
private ViewGroup mTrack;
private ScrollView mScroller;
private OnActionItemClickListener mItemClickListener;
private OnDismissListener mDismissListener;
private List<ActionItem> actionItems = new ArrayList<ActionItem>();
private boolean mDidAction;
private int mChildPos;
private int mInsertPos;
private int mAnimStyle;
private int mOrientation;
private int rootWidth=0;
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
public static final int ANIM_GROW_FROM_LEFT = 1;
public static final int ANIM_GROW_FROM_RIGHT = 2;
public static final int ANIM_GROW_FROM_CENTER = 3;
public static final int ANIM_REFLECT = 4;
public static final int ANIM_AUTO = 5;
/**
* Constructor for default vertical layout
*
* @param context Context
*/
public QuickAction(Context context) {
this(context, VERTICAL);
}
/**
* Constructor allowing orientation override
*
* @param context Context
* @param orientation Layout orientation, can be vartical or horizontal
*/
public QuickAction(Context context, int orientation) {
super(context);
mOrientation = orientation;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (mOrientation == HORIZONTAL) {
setRootViewId(R.layout.popup_horizontal);
} else {
setRootViewId(R.layout.popup_vertical);
}
mAnimStyle = ANIM_AUTO;
mChildPos = 0;
}
/**
* Get action item at an index
*
* @param index Index of item (position from callback)
*
* @return Action Item at the position
*/
public ActionItem getActionItem(int index) {
return actionItems.get(index);
}
/**
* Set root view.
*
* @param id Layout resource id
*/
public void setRootViewId(int id) {
mRootView = (ViewGroup) mInflater.inflate(id, null);
mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks);
mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down);
mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up);
mScroller = (ScrollView) mRootView.findViewById(R.id.scroller);
//This was previously defined on show() method, moved here to prevent force close that occured
//when tapping fastly on a view to show quickaction dialog.
//Thanx to zammbi (github.com/zammbi)
mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
setContentView(mRootView);
}
/**
* Set animation style
*
* @param mAnimStyle animation style, default is set to ANIM_AUTO
*/
public void setAnimStyle(int mAnimStyle) {
this.mAnimStyle = mAnimStyle;
}
/**
* Set listener for action item clicked.
*
* @param listener Listener
*/
public void setOnActionItemClickListener(OnActionItemClickListener listener) {
mItemClickListener = listener;
}
/**
* Add action item
*
* @param action {@link ActionItem}
*/
public void addActionItem(ActionItem action) {
actionItems.add(action);
String title = action.getTitle();
Drawable icon = action.getIcon();
View container;
if (mOrientation == HORIZONTAL) {
container = mInflater.inflate(R.layout.action_item_horizontal, null);
} else {
container = mInflater.inflate(R.layout.action_item_vertical, null);
}
ImageView img = (ImageView) container.findViewById(R.id.iv_icon);
TextView text = (TextView) container.findViewById(R.id.tv_title);
if (icon != null) {
img.setImageDrawable(icon);
} else {
img.setVisibility(View.GONE);
}
if (title != null) {
text.setText(title);
} else {
text.setVisibility(View.GONE);
}
final int pos = mChildPos;
final int actionId = action.getActionId();
container.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mItemClickListener != null) {
mItemClickListener.onItemClick(QuickAction.this, pos, actionId);
}
if (!getActionItem(pos).isSticky()) {
mDidAction = true;
dismiss();
}
}
});
container.setFocusable(true);
container.setClickable(true);
if (mOrientation == HORIZONTAL && mChildPos != 0) {
View separator = mInflater.inflate(R.layout.horiz_separator, null);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
separator.setLayoutParams(params);
separator.setPadding(5, 0, 5, 0);
mTrack.addView(separator, mInsertPos);
mInsertPos++;
}
mTrack.addView(container, mInsertPos);
mChildPos++;
mInsertPos++;
}
/**
* Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view.
*
*/
public void show (View anchor) {
preShow();
int xPos, yPos, arrowPos;
mDidAction = false;
int[] location = new int[2];
anchor.getLocationOnScreen(location);
Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
+ anchor.getHeight());
//mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
int rootHeight = mRootView.getMeasuredHeight();
if (rootWidth == 0) {
rootWidth = mRootView.getMeasuredWidth();
}
int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
//automatically get X coord of popup (top left)
if ((anchorRect.left + rootWidth) > screenWidth) {
xPos = anchorRect.left - (rootWidth-anchor.getWidth());
xPos = (xPos < 0) ? 0 : xPos;
arrowPos = anchorRect.centerX()-xPos;
} else {
if (anchor.getWidth() > rootWidth) {
xPos = anchorRect.centerX() - (rootWidth/2);
} else {
xPos = anchorRect.left;
}
arrowPos = anchorRect.centerX()-xPos;
}
int dyTop = anchorRect.top;
int dyBottom = screenHeight - anchorRect.bottom;
boolean onTop = (dyTop > dyBottom) ? true : false;
if (onTop) {
if (rootHeight > dyTop) {
yPos = 15;
LayoutParams l = mScroller.getLayoutParams();
l.height = dyTop - anchor.getHeight();
} else {
yPos = anchorRect.top - rootHeight;
}
} else {
yPos = anchorRect.bottom;
if (rootHeight > dyBottom) {
LayoutParams l = mScroller.getLayoutParams();
l.height = dyBottom;
}
}
showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
}
/**
* Set animation style
*
* @param screenWidth screen width
* @param requestedX distance from left edge
* @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view
* and vice versa
*/
private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
switch (mAnimStyle) {
case ANIM_GROW_FROM_LEFT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
break;
case ANIM_GROW_FROM_RIGHT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
break;
case ANIM_GROW_FROM_CENTER:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
break;
case ANIM_REFLECT:
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);
break;
case ANIM_AUTO:
if (arrowPos <= screenWidth/4) {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
} else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
} else {
mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
}
break;
}
}
/**
* Show arrow
*
* @param whichArrow arrow type resource id
* @param requestedX distance from left screen
*/
private void showArrow(int whichArrow, int requestedX) {
final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
final int arrowWidth = mArrowUp.getMeasuredWidth();
showArrow.setVisibility(View.VISIBLE);
ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
param.leftMargin = requestedX - arrowWidth / 2;
hideArrow.setVisibility(View.INVISIBLE);
}
/**
* Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed
* by clicking outside the dialog or clicking on sticky item.
*/
public void setOnDismissListener(QuickAction.OnDismissListener listener) {
setOnDismissListener(this);
mDismissListener = listener;
}
@Override
public void onDismiss() {
if (!mDidAction && mDismissListener != null) {
mDismissListener.onDismiss();
}
}
/**
* Listener for item click
*
*/
public interface OnActionItemClickListener {
public abstract void onItemClick(QuickAction source, int pos, int actionId);
}
/**
* Listener for window dismiss
*
*/
public interface OnDismissListener {
public abstract void onDismiss();
}
}
//--------------- Create Another Class------------------------------------------------------------------------
public class PopupWindows {
protected Context mContext;
protected PopupWindow mWindow;
protected View mRootView;
protected Drawable mBackground = null;
protected WindowManager mWindowManager;
/**
* Constructor.
*
* @param context Context
*/
public PopupWindows(Context context) {
mContext = context;
mWindow = new PopupWindow(context);
mWindow.setTouchInterceptor(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
mWindow.dismiss();
return true;
}
return false;
}
});
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
/**
* On dismiss
*/
protected void onDismiss() {
}
/**
* On show
*/
protected void onShow() {
}
/**
* On pre show
*/
protected void preShow() {
if (mRootView == null)
throw new IllegalStateException("setContentView was not called with a view to display.");
onShow();
if (mBackground == null)
mWindow.setBackgroundDrawable(new BitmapDrawable());
else
mWindow.setBackgroundDrawable(mBackground);
mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
mWindow.setTouchable(true);
mWindow.setFocusable(true);
mWindow.setOutsideTouchable(true);
mWindow.setContentView(mRootView);
}
/**
* Set background drawable.
*
* @param background Background drawable
*/
public void setBackgroundDrawable(Drawable background) {
mBackground = background;
}
/**
* Set content view.
*
* @param root Root view
*/
public void setContentView(View root) {
mRootView = root;
mWindow.setContentView(root);
}
/**
* Set content view.
*
* @param layoutResID Resource id
*/
public void setContentView(int layoutResID) {
LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
setContentView(inflator.inflate(layoutResID, null));
}
/**
* Set listener on window dismissed.
*
* @param listener
*/
public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
mWindow.setOnDismissListener(listener);
}
/**
* Dismiss the popup window.
*/
public void dismiss() {
mWindow.dismiss();
}
}
//Defining Action Items with Quick menu
/**
* Action item, displayed as menu with icon and text.
*/
public class ActionItem {
private Drawable icon;
private Bitmap thumb;
private String title;
private int actionId = -1;
private boolean selected;
private boolean sticky;
/**
* Constructor
*
* @param actionId Action id for case statements
* @param title Title
* @param icon Icon to use
*/
public ActionItem(int actionId, String title, Drawable icon) {
this.title = title;
this.icon = icon;
this.actionId = actionId;
}
/**
* Constructor
*/
public ActionItem() {
this(-1, null, null);
}
/**
* Constructor
*
* @param actionId Action id of the item
* @param title Text to show for the item
*/
public ActionItem(int actionId, String title) {
this(actionId, title, null);
}
/**
* Constructor
*
* @param icon {@link Drawable} action icon
*/
public ActionItem(Drawable icon) {
this(-1, null, icon);
}
/**
* Constructor
*
* @param actionId Action ID of item
* @param icon {@link Drawable} action icon
*/
public ActionItem(int actionId, Drawable icon) {
this(actionId, null, icon);
}
/**
* Set action title
*
* @param title action title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Get action title
*
* @return action title
*/
public String getTitle() {
return this.title;
}
/**
* Set action icon
*
* @param icon {@link Drawable} action icon
*/
public void setIcon(Drawable icon) {
this.icon = icon;
}
/**
* Get action icon
* @return {@link Drawable} action icon
*/
public Drawable getIcon() {
return this.icon;
}
/**
* Set action id
*
* @param actionId Action id for this action
*/
public void setActionId(int actionId) {
this.actionId = actionId;
}
/**
* @return Our action id
*/
public int getActionId() {
return actionId;
}
/**
* Set sticky status of button
*
* @param sticky true for sticky, pop up sends event but does not disappear
*/
public void setSticky(boolean sticky) {
this.sticky = sticky;
}
/**
* @return true if button is sticky, menu stays visible after press
*/
public boolean isSticky() {
return sticky;
}
/**
* Set selected flag;
*
* @param selected Flag to indicate the item is selected
*/
public void setSelected(boolean selected) {
this.selected = selected;
}
/**
* Check if item is selected
*
* @return true or false
*/
public boolean isSelected() {
return this.selected;
}
/**
* Set thumb
*
* @param thumb Thumb image
*/
public void setThumb(Bitmap thumb) {
this.thumb = thumb;
}
/**
* Get thumb image
*
* @return Thumb image
*/
public Bitmap getThumb() {
return this.thumb;
}
}

Awesome Gallery With Android....

Gallery With Reflection



//Main Activity
public class TryGallaryActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Integer[] images = { R.drawable.img0001, R.drawable.img0030,
R.drawable.img0100, R.drawable.img0130, R.drawable.img0200,
R.drawable.img0230, R.drawable.img0300, R.drawable.img0330,
R.drawable.img0354 };
ImageAdapter adapter = new ImageAdapter(this, images);
adapter.createReflectedImages();
GalleryFlow galleryFlow = (GalleryFlow) findViewById(R.id.Gallery01);
galleryFlow.setAdapter(adapter);
}
}
//For Rotation make one class GalleryFlow
public class GalleryFlow extends Gallery {
private Camera mCamera = new Camera();
private int mMaxRotationAngle = 60;
private int mMaxZoom = -120;
private int mCoveflowCenter;
public GalleryFlow(Context context) {
super(context);
this.setStaticTransformationsEnabled(true);
}
public GalleryFlow(Context context, AttributeSet attrs) {
super(context, attrs);
this.setStaticTransformationsEnabled(true);
}
public GalleryFlow(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.setStaticTransformationsEnabled(true);
}
public int getMaxRotationAngle() {
return mMaxRotationAngle;
}
public void setMaxRotationAngle(int maxRotationAngle) {
mMaxRotationAngle = maxRotationAngle;
}
public int getMaxZoom() {
return mMaxZoom;
}
public void setMaxZoom(int maxZoom) {
mMaxZoom = maxZoom;
}
private int getCenterOfCoverflow() {
return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
+ getPaddingLeft();
}
private static int getCenterOfView(View view) {
return view.getLeft() + view.getWidth() / 2;
}
protected boolean getChildStaticTransformation(View child, Transformation t) {
final int childCenter = getCenterOfView(child);
final int childWidth = child.getWidth();
int rotationAngle = 0;
t.clear();
t.setTransformationType(Transformation.TYPE_MATRIX);
if (childCenter == mCoveflowCenter) {
transformImageBitmap((ImageView) child, t, 0);
} else {
rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
if (Math.abs(rotationAngle) > mMaxRotationAngle) {
rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
: mMaxRotationAngle;
}
transformImageBitmap((ImageView) child, t, rotationAngle);
}
return true;
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCoveflowCenter = getCenterOfCoverflow();
super.onSizeChanged(w, h, oldw, oldh);
}
private void transformImageBitmap(ImageView child, Transformation t,
int rotationAngle) {
mCamera.save();
final Matrix imageMatrix = t.getMatrix();
final int imageHeight = child.getLayoutParams().height;
final int imageWidth = child.getLayoutParams().width;
final int rotation = Math.abs(rotationAngle);
mCamera.translate(0.0f, 0.0f, 100.0f);
// As the angle of the view gets less, zoom in
if (rotation < mMaxRotationAngle) {
float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
mCamera.translate(0.0f, 0.0f, zoomAmount);
}
mCamera.rotateY(rotationAngle);
mCamera.getMatrix(imageMatrix);
imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
mCamera.restore();
}
}
//And at last Image Adapter for Reflection and Shadow Effect...
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private Integer[] mImageIds;
private ImageView[] mImages;
public ImageAdapter(Context c, Integer[] ImageIds) {
mContext = c;
mImageIds = ImageIds;
mImages = new ImageView[mImageIds.length];
}
public boolean createReflectedImages() {
final int reflectionGap = 4;
int index = 0;
for (int imageId : mImageIds) {
Bitmap originalImage = BitmapFactory.decodeResource(mContext
.getResources(), imageId);
int width = originalImage.getWidth();
int height = originalImage.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,
height / 2, width, height / 2, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
(height + height / 2), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(originalImage, 0, 0, null);
Paint deafaultPaint = new Paint();
canvas.drawRect(0, height, width, height + reflectionGap,
deafaultPaint);
canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, originalImage
.getHeight(), 0, bitmapWithReflection.getHeight()
+ reflectionGap, 0x70ffffff, 0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap(bitmapWithReflection);
imageView.setLayoutParams(new GalleryFlow.LayoutParams(450,300));
// imageView.setScaleType(ScaleType.MATRIX);
mImages[index++] = imageView;
}
return true;
}
private Resources getResources() {
// TODO Auto-generated method stub
return null;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
return mImages[position];
}
public float getScale(boolean focused, int offset) {
return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
///return 1;
}
}
//Your main.xml should be like this ...
/*
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
>
<com.test.gly.GalleryFlow
android:id="@+id/Gallery01"
android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_centerInParent="true"/>
</RelativeLayout>
*/