Saturday, October 6, 2012

View and layoutparams

View Hierarchy

When creating views programmatically, there are rules to remember:

1. Each view has it's own layoutparams settings
2. layoutparams has different classes, depending on the parent of the view

For example, the layoutparams for a textview within a linearlayout and a textview with a relativelayout use different class - linearlayout.layoutparams and relativelayout.layoutparams.

Using incompatible layoutparams for views will crash the graphic creation engine.

Layoutparams are sometimes created automatically or are requires definition.

Example,

TextView tv = new TextView(context);
CurrentLayout.add (tv); //adds view and automatically assign currentlayout layoutparams into tv

or

TextView tv = new TextView(context);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(100,100); //set width and height to 100
tv.setLayoutParams( lparams);
CurrentLayout.add (tv); //Current Layout MUST be a linearlayout or an exception will be raise

Sunday, September 23, 2012

Back to basic

Let's look at activity basic - How we can maintain a view as android recycle it's view either when it switch from vertical view to horizontal view or vice-versa.

Within activity at java code level
public class UIACTIVITY extends Activity {

//There are two views we have in this app
int activityLayoutA = R.layout.ViewA;
int activityLayoutB = R.layout.ViewB;
int currentActivity = R.layout.ViewA; //defaultview

//single method to view which view is to be constructed
public void switchAppWideViews(int LayoutView){
setContentView(LayoutView);
if(LayoutView == activityLayoutA){
//LAYOUT ACTIVITY A SETTINGS HERE
}

if(LayoutView == activityLayoutB){
//LAYOUT ACTIVITY B SETTINGS HERE
}
currentActivity = LayoutView; //set a current view

}


@Override
    public void onCreate(Bundle savedInstanceState) {
//Standard create view on switch
           super.onCreate(savedInstanceState);

//savedInstanceState will be null if it is launched for the first time
        if(savedInstanceState==null){       
        switchAppWideViews(authenLayout);
        }else{

//activity already launched

                int cLayout = (Integer) savedInstanceState.get("CURRENTLAYOUT");
        switchAppWideViews(cLayout);


        }


@Override
    protected void onSaveInstanceState(Bundle outState) {
//Save current layout before view is destroyed
    outState.putInt("CURRENTLAYOUT", currentActiveLayout);
    super.onSaveInstanceState(outState);
    }



}

Sunday, September 16, 2012

Statelistdrawables 2

A simpler mechanism to custom statelistdrawables

private Button newbutton(){
Button new = new Button(context);
new.setBackgroundDrawable(custombtnstate());

}



private StateListDrawable custombtnstate(){
StateListDrawable draw = new StateListDrawable();
Drawable bkgd = new Drawable(){

@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawColor(Color.rgb(22, 33, 44)); //Custom color 1
}

@Override
public int getOpacity() {
// TODO Auto-generated method stub
return 0;
}

@Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}

@Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}

};

Drawable bkgd1 = new Drawable(){

@Override
public void draw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawColor(Color.rgb(150, 180, 190));//Custom color 2
}

@Override
public int getOpacity() {
// TODO Auto-generated method stub
return 0;
}

@Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}

@Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}

};
//Essential
 
int stateFocused = android.R.attr.state_focused;
int statePressed = android.R.attr.state_pressed;
int stateSelected = android.R.attr.state_selected;

draw.addState(new int[] {statePressed}, bkgd1);
draw.addState(new int[] {stateSelected},  bkgd1);
draw.addState(new int[] {stateFocused},  bkgd1);
draw.addState(new int[] {-stateFocused,  -statePressed, -stateSelected}, bkgd);


return draw;
}

Wednesday, May 16, 2012

Making a circle with different reactive arcs


This post will summarize the creation of a circle with arcs

1. Class that contains a single pieItem
2. method that bind multiple pieItems into 1 single layout
3. Insert the layout into your main view as a single element

1.Class that contains a single pieItem
This class will extend Views, and override OnTouchEvent.
2 things will happen to this custom view. First, it will draw a circle arc based on start point on a plane. Second, it intercept a touchevent and check that the angle of the touch to it's center point matches the angle of the circle arc created (boundary = start point, end point = start point + sweep point). If true, we can then react/set an action

2. Method that bind muliple pieItems - this have to be in the UI
Create a relativelayout, and house all pieItems view into the relativelayout without positioning. This will create a illusion that the views are a circle, since they are all position as 1,1 - where the non-arc portion is transparent.

Thursday, September 15, 2011

A closer look into Listview

This is about understanding listviews.

There are a few component to a listview in Android

1. The view
2. The arrayadapter
3. The data
4. The listener
5. A customised look

Standard declaration:
//base listview
Listview lview = (ListView) findViewById(R.id.AlistViewInXML);
lview.setAdapter(aAdapt);

//data-binding
We can use objects in binding data - since we can define objects - we can define values individually. We can also use ArrayList to house multiple objects.

For example, a object with three values - obj.V1, obj.V2 and obj.V3 each representing different values.

//customised look
We can design a view to be house into a item in a ListView. For instance, we can have 1 single layout view housing 3 separate textviews - tv1, tv2, tv3.


//declare new arrayadapter for our listview
// this arrayadapter will house 1. The data and the listener. But we can't use the standard listview if we wish to customise the listview. Thus, we will need to overload this standard call:

ArrayAdapter aAdapt = new ArrayAdapter (context, ViewToShowAsASingleItem, Data){


@Override
public View getView(int position, View cv, ViewGroup parent){
//arrange your ListView appearance
View rw = cv; //This is the view per item
buildAHolder hold;

if(rw == null){
//Set item appearance - when null, the item is recycled
LayoutInflater inflater=getLayoutInflater();
hold = new buildAHolder();
//with a holder - we can do referencing
hold.H_A = (TextView)((View) rw).findViewById(R.id.tv1);
hold.H_B = (TextView)((View) rw).findViewById(R.id.tv2);
hold.H_C = (TextView)((View) rw).findViewById(R.id.tv3);
//Use Tag to hold the holder class for retrieval subsequently
rw.setTag(hold);
hold.H_A.setTag(position);
} else {
// Get the ViewHolder back to get fast access to the TextViews
hold = (buildAHolder) rw.getTag();
hold.H_A.setTag(position);
}//End row recycling
//Set Data items to views
hold.H_A .setText(super.getItem(position).V1.toString());
hold.H_B .setText(super.getItem(position).V2.toString());
hold.H_C .setText(super.getItem(position).V3.toString());

cv.setOnClickListener(CustomclickListener); //you can choose where to put this
return cv;
} //End getView
OnClickListener CustomclickListener = new OnClickListener(){
public void onClick(View v) {
//Actions on click
}
}; //End onclicklistener
class buildAHolder{
//house views
TextView H_A; TextView H_B; TextView H_C;
}//End class

}; //End aAdapt

That's it about ListView - adapters
Notice also that we can do references with objects

1. Setup method to store and return View in an object. eg - setView and getView.
2. With setView, we can then set the preferred Layout into the object
3. Then use getView within the arrayadapter to extract the relevant view

Example:
View SelectedView;
if(a==true){SelectedView = (Layout) findViewById(R.Layout.Layout1;}
else{SelectedView = (Layout) findViewById(R.Layout.Layout2;}

obj.get(0).setView = SelectedView;

//In arrayadapater overloading
ArrayAdapter aAdapt = new ArrayAdapter (context, 1, Data){
public View getView(int position, View cv, ViewGroup parent){
if (position==0){//only reference view once first position
cv = obj.get(0)getView; // Note how normal textviewresourceid is any value (1 here)
}
View row = cv;

.... rest of code
}

}




Friday, August 26, 2011

Gradients -- A deeper look


There is a setShader function within drawables. The following simplify coloring of a drawable object:

ShapeDrawable aDrawable = new ShapeDrawable(new OvalShape());
LinearGradient AGradient = new LinearGradient(x, y, x1, y1, LeftTopColor, RightbottomColor, Shader.TileMode.CLAMP);
aDrawable.getPaint().setShader(AGradient);

The result of simple manipulation on x, y, x1, y1



coding -
Butn 1 - new LinearGradient(0, 0, 50, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 2 - new LinearGradient(0, 0, 0, 50, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 3 - new LinearGradient(50, 0, 0, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 4 - new LinearGradient(0, 50, 0, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);




With the absence of either x or y, we have a gradient from x to y (Either top to bottom or right to left). With x and y (as below), we will have a gradient from top-left to bottom-right or top-right to bottom-left.

My belief is that x,y forms the coordinates for color1 and x1,y1 forms the coordinates for color2.
The distance between x1,y1 and x,y determines the direction of the gradient and angle.

shifting the numbers slightly
Butn 1 - new LinearGradient(0, 0, 50, 50, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 2 - new LinearGradient(0, 0, 100, 100, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 3 - new LinearGradient(50, 50, 0, 0,ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 4 - new LinearGradient(100, 100, 0, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);

result:




Butn 1 - new LinearGradient(50, 50, 50, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 2 - new LinearGradient(0, 50, 50, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 3 - new LinearGradient(50, 0, 50, 0,ColorYellow, ColorRed, Shader.TileMode.CLAMP);
Butn 4 - new LinearGradient(0, 0,50, 0, ColorYellow, ColorRed, Shader.TileMode.CLAMP);


Saturday, August 20, 2011

State List Drawables

It takes a long time to figure this out by referring to documentation

The objective is to make a customizable button that reacts to user-touch input

In android, there are many states to a View in any particular time. State List Drawables can be used to control the appearance of the View in reaction to the particular state.

In this example i will have two buttons, each having a single statelistdrawable and a onClickListener that will change the other's state.


--------------------------- A statelistdrawable subclass --------------------------------

public class ImDraw extends StateListDrawable {
int alphaValue; int heightValue; int widthValue;
Canvas canvasIM;
ColorFilter cFilter;
StateListDrawable ImSLDrawable;
Drawable ImDrawable; Drawable ImDrawable1; Drawable ImDrawable2;
Paint paintIM;
int xHeight; int xWidth;
int currentType;
public ImDraw(int drawType, int intHeight, int intWidth){
//Set default values on start
alphaValue = 255;
cFilter = new ColorFilter();
currentType = drawType; xHeight = intHeight; xWidth = intWidth;
}
public StateListDrawable getSLD(){
//Set drawables colors
int drawColor1 = Color.argb(alphaValue, 255, 0, 0); //Paint Red
int drawColor2 = Color.argb(alphaValue, 255, 255, 0); //Paint Yellow
int drawColor3 = Color.argb(alphaValue, 255, 255, 255); //Paint White

//Draw desired drawables for the states - note the sub-class of normalSingleDrawables
normalSingleDrawables nSDA = new normalSingleDrawables(1, xHeight, xWidth, drawColor1, alphaValue);
normalSingleDrawables nSDB = new normalSingleDrawables(1, xHeight, xWidth, drawColor2, alphaValue);
normalSingleDrawables nSDC = new normalSingleDrawables(1, xHeight, xWidth, drawColor3, alphaValue);
ImSLDrawable = new StateListDrawable();
//Setup states to android.attr state
// int stateChecked = android.R.attr.state_checked;
int stateFocused = android.R.attr.state_focused;
int statePressed = android.R.attr.state_pressed;
int stateSelected = android.R.attr.state_selected;
//Set states --- notice 15 is setup as an additional, outside android.attr state
ImSLDrawable.addState(new int[] {15}, nSDC);
ImSLDrawable.addState(new int[] {statePressed}, nSDA);
ImSLDrawable.addState(new int[] {stateSelected}, nSDA);
ImSLDrawable.addState(new int[] {stateFocused}, nSDA);
ImSLDrawable.addState(new int[] {-stateFocused, -statePressed, -stateSelected}, nSDB);
return ImSLDrawable;

}
// ----- Start sub-class
class normalSingleDrawables extends Drawable{
int alphaValue;
int xPos = 1 ;int yPos = 1;
int xWidth; int yHeight;
int paintcolor;

public normalSingleDrawables(int choice, int intHeight, int intWidth, int dPaint, int alpha) {
xWidth = intWidth; yHeight = intHeight;
paintcolor = dPaint;
alphaValue = alpha;

//set the shape of drawable based on values

switch (choice) {
case 1: //Draw a rectangle
ImDrawable = new ShapeDrawable(new RectShape());
break;
case 2: //Draw a circle
ImDrawable = new ShapeDrawable(new OvalShape());
break;
default: //Draw a rectangle
ImDrawable = new ShapeDrawable(new RectShape());
} }

public void draw(Canvas canvasIM) {
((ShapeDrawable) ImDrawable).getPaint().setColor(paintcolor);
ImDrawable.setBounds(xPos, yPos, xPos + xWidth ,yPos + yHeight);
ImDrawable.draw(canvasIM); }

@Override
public int getOpacity() {
return PixelFormat.OPAQUE; }

@Override
public void setAlpha(int newAlphaValue) {
alphaValue = newAlphaValue; }

@Override
public void setColorFilter(ColorFilter cf) {
cf = cFilter; }
}

// ----- End sub-class
}

--------------------------- A statelistdrawable subclass --------------------------------
------------------------ On Application main activity --------------------------------
public class MYIM extends Activity {
//Default
TextView mainTextView;
String Msg = "";
Button mainButton = null; Button SideButton = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
//default activity code
super.onCreate(savedInstanceState);
//reference main.xml as User Interface
setContentView(R.layout.main);
//Set references point to our main.xml file - there must be two buttons with id -btnMain and btnSide
mainButton = (Button) findViewById(R.id.btnMain);
SideButton = (Button) findViewById(R.id.btnSide);
//Create our custom SLD
//Set drawables for our buttons
ImDraw NewIM = new ImDraw(1,
mainButton.getLayoutParams().height, mainButton.getLayoutParams().width);
mainButton.setBackgroundDrawable(NewIM.getSLD());

NewIM = new ImDraw(1,
SideButton.getLayoutParams().height, SideButton.getLayoutParams().width);
SideButton.setBackgroundDrawable(NewIM.getSLD());

//Set onClick for our buttons
mainButton.setOnClickListener(new OnClickListener(){
public void onClick(View view){
//Switch the other button to State No 15!
SideButton.getBackground().setState(new int[]{15});
}
});
SideButton.setOnClickListener(new OnClickListener(){
public void onClick(View view){
//Switch the other button to State No 15!
mainButton.getBackground().setState(new int[]{15});
}
});

}
}