Android Runtime Layout Tutorial - android

Does anyone know how to perform or have a good reference for doing an activity layout at runtime in android?
Here is the code for my activity. I'm sure I'm just neglecting to do something here:
package com.isi.sa;
import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
public class SimpleAssessmentTest extends Activity {
LinearLayout layout;
TextView question;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
layout = new LinearLayout(this);
question = new TextView(this);
layout.setLayoutParams(new ViewGroup.LayoutParams(-1,-1));
layout.setBackgroundColor(R.color.blue);
question.setLayoutParams(new ViewGroup.LayoutParams(-1,-2));
question.setTextColor(R.color.green);
question.setTextSize(1,14);
question.setText("This is question1");
layout.addView(question);
setContentView(layout);
}
}
As you can see I'm just trying to add a linear layout with a single text view (just for testing purposes) however, when the activity starts I just get a black screen with a title bar of my app name.
Thanks

You forgot to set your contentView. You should add
setContentView(layout);
At the end of the onCreate method

You can check out this URL: http://www.linux-mag.com/cache/7705/1.html . It has both library widgets and custom widgets.
EDIT:
setBackgroundColor requires input in proper ARGB format: 0xAARRGGBB. Each AA, RR, GG and BB range from 00 (minimum) to ff (maximum).
The bare minimum example goes here and it works flawlessly. Here are the screenshot and code (modified a bit):
http://picturepush.com/public/3313522 (old)
package us.simpleit;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class SimpleGUI extends Activity {
TextView tv;
EditText et;
LinearLayout ll;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//LinearLayout ll = new LinearLayout(this);
ll = new LinearLayout(this);
ll.setOrientation(android.widget.LinearLayout.VERTICAL);
ll.setLayoutParams(new ViewGroup.LayoutParams(-1,-1));
// ARGB: Opaque Red
ll.setBackgroundColor(0x88ff0000);
tv = new TextView(this);
tv.setLayoutParams(new ViewGroup.LayoutParams(-1,-2));
tv.setText("sample text goes here");
// ARGB: Opaque Green
tv.setBackgroundColor(0x5500ff00);
ll.addView(tv);
et = new EditText(this);
et.setLayoutParams(new ViewGroup.LayoutParams(-1,-2));
et.setText("edit me please");
// ARGB: Solid Blue
et.setBackgroundColor(0xff0000ff);
ll.addView(et);
Button btn = new Button(this);
btn.setText("Go!");
btn.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
tv.setText(et.getText().toString());
}
});
ll.addView(btn);
setContentView(ll);
//setContentView(R.layout.main);
}
}

The following demonstrates how to create views and layouts programmatically without using the layout xml files. It also creates a rounded rectangle layout object that draws a rounded rectangle around any child objects that are placed in it.
package android.example;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MessageScreen extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int mainBackgroundColor = Color.parseColor("#2E8B57");
int labelTextColor = Color.parseColor("#FF4500");
int messageBackgroundColor = Color.parseColor("#3300FF");
int messageTextColor = Color.parseColor("#FFFF00");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
int minMarginSize = Math.round(density * 8);
int paddingSize = minMarginSize * 2;
int maxMarginSize = minMarginSize * 4;
TextView label = new TextView(this);
/*
* The LayoutParams are instructions to the Layout that will contain the
* View for laying out the View, so you need to use the LayoutParams of
* the Layout that will contain the View.
*/
LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
label.setLayoutParams(labelLayoutParams);
label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
label.setText(R.string.title);
label.setTextColor(labelTextColor);
TextView message = new TextView(this);
RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This tells the RoundedRectangle to put some extra space around the
* View.
*/
messageLayoutParams.setMargins(minMarginSize, paddingSize,
minMarginSize, maxMarginSize);
message.setLayoutParams(messageLayoutParams);
message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
message.setText(R.string.message);
message.setTextColor(messageTextColor);
message.setBackgroundColor(messageBackgroundColor);
RoundedRectangle messageContainer = new RoundedRectangle(this);
LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
messageContainer.setLayoutParams(messageContainerLayoutParams);
messageContainer.setOrientation(LinearLayout.VERTICAL);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This tells the RoundedRectangle to color the the exta space that was
* put around the View as well as the View. This is exterior color of
* the RoundedRectangle.
*/
messageContainer.setBackgroundColor(mainBackgroundColor);
/*
* This is one of the calls must made to force a ViewGroup to call its
* draw method instead of just calling the draw method of its children.
* This is the interior color of the RoundedRectangle. It must be
* different than the exterior color of the RoundedRectangle or the
* RoundedRectangle will not call its draw method.
*/
messageContainer.setInteriorColor(messageBackgroundColor);
// Add the message to the RoundedRectangle.
messageContainer.addView(message);
//
LinearLayout main = new LinearLayout(this);
LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
main.setLayoutParams(mainLayoutParams);
main.setOrientation(LinearLayout.VERTICAL);
main.setBackgroundColor(mainBackgroundColor);
main.addView(label);
main.addView(messageContainer);
setContentView(main);
}
}
The class for RoundedRectangle layout object is as defined here:
/**
* A LinearLayout that draws a rounded rectangle around the child View that was added to it.
*/
package android.example;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;
/**
* A LinearLayout that has rounded corners instead of square corners.
*
* #author Danny Remington
*
* #see LinearLayout
*
*/
public class RoundedRectangle extends LinearLayout {
private int mInteriorColor;
public RoundedRectangle(Context p_context) {
super(p_context);
}
public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
super(p_context, attributeSet);
}
// Listener for the onDraw event that occurs when the Layout is drawn.
protected void onDraw(Canvas canvas) {
Rect rect = new Rect(0, 0, getWidth(), getHeight());
RectF rectF = new RectF(rect);
DisplayMetrics metrics = new DisplayMetrics();
Activity activity = (Activity) getContext();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
int arcSize = Math.round(density * 10);
Paint paint = new Paint();
paint.setColor(mInteriorColor);
canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
}
/**
* Set the background color to use inside the RoundedRectangle.
*
* #param Primitive int - The color inside the rounded rectangle.
*/
public void setInteriorColor(int interiorColor) {
mInteriorColor = interiorColor;
}
/**
* Get the background color used inside the RoundedRectangle.
*
* #return Primitive int - The color inside the rounded rectangle.
*/
public int getInteriorColor() {
return mInteriorColor;
}
}

I'm not sure if this question has been answered or not, but I just overcame this same issue today. Viet touched on the issue above but did not explicitly point out to check your color values. If you're coming from J2ME background like myself, you might be defining your color int values as 0xRRGGBB, so for full red J2ME would define it as 0xFF0000. However, doing so on Android will result in an int value of 0x00FF0000. Because Android uses the format of 0xAARRGGBB, a value of 0xFF0000 (J2ME) is actually (0x00FF0000) in Android this is full Red color that is COMPLETLY TRANSPARENT, so it's not seen on screen.
I Noticed above in your code you're using question.setTextColor(R.color.green); This statement will assign the id value created in the R file, so it's probably a high number with some value as 0x7f050000 where the Alpha is set lower than FULL OPAQUE. Try your example with:
question.setTextColor( getResources().getColor( R.color.green ) );
This should set the text color to the value in R.color.green not the ID of R.color.green.

Related

Adjust size and gap between FancyButton placed on LinearLayout

I have placed programmatically generated FancyButtons on LinearLayout. But, the generated buttons are placed too compactly, in other words, there is no separation between two successive buttons. Also, I want the buttons to stretch entire with of the layout. I tried btnWordList.setMinimumWidth(MATCH_PARENT) without any result. Please find the code below.
FlexDict.java
package in.dipanjan.flexdict;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.graphics.Color;
import android.content.Intent;
import android.widget.LinearLayout;
import android.graphics.PixelFormat;
import mehdi.sakout.fancybuttons.FancyButton;
import android.support.v7.app.ActionBarActivity;
public class FlexDict extends ActionBarActivity implements View.OnClickListener {
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
Window window = getWindow();
window.setFormat(PixelFormat.RGBA_8888);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int listCount, wordLists = 5;
/* http://stackoverflow.com/questions/19078461/android-null-pointer-exception-findviewbyid */
setContentView(R.layout.activity_flex_dict);
LinearLayout container = (LinearLayout)findViewById(R.id.container);
for(listCount = 1; listCount <= wordLists; listCount++)
{
/* https://github.com/medyo/fancybuttons */
FancyButton btnWordList = new FancyButton(this);
btnWordList.setId(listCount);
btnWordList.setText("WordList " + listCount);
btnWordList.setBackgroundColor(Color.parseColor("#3b5998"));
btnWordList.setFocusBackgroundColor(Color.parseColor("#5474b8"));
btnWordList.setTextSize(20);
btnWordList.setIconResource("\uf04b");
btnWordList.setRadius(10);
btnWordList.setOnClickListener(this);
container.addView(btnWordList);
}
setContentView(container);
}
#Override
public void onClick(View view) {
int wordList = view.getId();
/*
* http://www.java-samples.com/showtutorial.php?tutorialid=1525
* http://stackoverflow.com/questions/7980627/pressing-back-button-did-not-go-back-to-previous-activity-android
*/
Bundle params = new Bundle();
params.putInt("WordList", wordList);
Intent intent = new Intent(this, ShowList.class);
intent.putExtras(params);
startActivity(intent);
}
}
activity_flex_dict.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#drawable/radialback">
</LinearLayout>
UI
http://s26.postimg.org/rkb0r4ys9/Fancy_Button.png
You need to setLayoutParams on your View.
i.e. btnWordList.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
You need to set layout params for any view even if instantiated in XML or Programatically.
http://developer.android.com/reference/android/view/View.html#setLayoutParams(android.view.ViewGroup.LayoutParams)
Set the layout parameters associated with this view. These supply parameters to the parent of this view specifying how it should be arranged. There are many subclasses of ViewGroup.LayoutParams, and these correspond to the different subclasses of ViewGroup that are responsible for arranging their children.
You need to set a margin between your buttons to make a gab between your buttons. and set your width to match_parent to make the button stretch to the width of the layout
int marginBottom = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
5,
r.getDisplayMetrics()
);
for(listCount = 1; listCount <= wordLists; listCount++)
{
/* https://github.com/medyo/fancybuttons */
FancyButton btnWordList = new FancyButton(this);
btnWordList.setId(listCount);
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT
);
params.setMargins(0, 0, 0, marginBottom);
btnWordList.setLayoutParams(params);
btnWordList.setText("WordList " + listCount);
btnWordList.setBackgroundColor(Color.parseColor("#3b5998"));
btnWordList.setFocusBackgroundColor(Color.parseColor("#5474b8"));
btnWordList.setTextSize(20);
btnWordList.setIconResource("\uf04b");
btnWordList.setRadius(10);
btnWordList.setOnClickListener(this);
container.addView(btnWordList);
}
You can use LayoutParam with margin
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
lp.bottumMargin = 2;
// or
lp.setMargins(0,0,0,2);
btnWordList.setLayoutParams(lp);

Drawing shapes programmatically for Android

I'm new to the Android SDK so I'm trying to figure this out. I have read the documentation and a text book and they haven't been particularly helpful in this matter.
I'm just trying to draw a simple rectangle in a linear layout on the screen. I can't get the shape to show up, however, when I add text to this layout in the same fashion, the text does show up. What am I missing?
package jorge.jorge.jorge;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ShapesActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ShapeDrawable rect = new ShapeDrawable(new RectShape());
rect.getPaint().setColor(Color.GREEN);
ImageView view1 = new ImageView(this);
view1.setImageDrawable(rect);
LinearLayout frame = (LinearLayout)findViewById(R.id.linear1);
frame.addView(view1);
// TextView tx = new TextView(this);
//
// tx.setText("Hello World");
//
// frame.addView(tx);
}
}
The Shape is usually used for making a background to some View. Its width and height is the same of the view that is using it. Then, if this view has no width and height, It'll have no width and height, too.
Basically, I think that your ImageView has no width and height, then it's invisible.
You can see how to set it programatically here:
Set ImageView width and height programmatically?
But, I recomend you to make the layout in XML's way.

Why does my RelativeLayout background become black when I add a button to it?

I have some code below that creates a RelativeLayout and adds a button to it. It draws fine when created from onCreate(), shows a blue button on a red background.
But when creating a new ReltativeLayout when clicking on the first the new button shows on a black background, so my RelativeLayout doesn't show.
The funny thing is that it works if I comment out the line that adds the button, so somehow the button is impacting the relative layout.
Thanks for any help.
package com.android.mikeviewtester;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
public class ViewTesterActivity extends Activity {
void createNewView( int bgColor, int btnColor ) {
// create a new relative layout
android.widget.RelativeLayout newView = new android.widget.RelativeLayout( this );
// create a button
Button btn = new Button( this );
// set the background color
btn.setBackgroundColor( btnColor );
// create a layoutParams struct for adding the button to the relative layout view
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( 100, 100 );
// add the button to the relative layout
newView.addView( btn, params );
// set the relative layout background color
newView.setBackgroundColor( bgColor );
// set the ontouch listener for the relativeLayout
newView.setOnTouchListener( (android.view.View.OnTouchListener) mOnTouchListener );
// create the layout to fill the activity
RelativeLayout.LayoutParams viewParams = new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
// set the relative layout as the view
setContentView( newView, viewParams );
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
// create and set the initial view
createNewView( Color.RED, Color.BLUE );
}
// ios - (void)buttonWasPressed:(id)whichButton {
private android.view.View.OnTouchListener mOnTouchListener = new android.view.View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if ( v != null )
v.onTouchEvent( event );
if ( event.getAction() == MotionEvent.ACTION_UP ) {
// create and set a new view
createNewView( Color.GREEN, Color.MAGENTA );
}
return true;
}
};
}
Make a change in your code, i.e. add v.setVisibility(View.GONE); before calling createNewView(Color.GREEN, Color.MAGENTA);

how to draw a ImageView in the middle of the screen? (programatically)

I want to draw a simple ImageView in the middle of the screen, horizontally and vertically. But i want to do it without using XML files, i need to do it programatically.
I tryed with the next code, but it doesn't works fine, it draws the image a little to the right and a little to the bottom. How to solve it?
ARImage = new ImageView(getApplicationContext());
ARImage.setImageResource(R.drawable.x);
rl.addView(ARImage); //rl is the relative layout that it's inserted into a frame layout
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int w = display.getWidth();
int h = display.getHeight();
RelativeLayout.LayoutParams position = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
position.leftMargin = (int)(w/2);
position.topMargin = (int)(h/2);
ARImage.setLayoutParams(position);
It works for me like this:
package pete.android.study;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
public class Main extends Activity {
/*
* (non-Javadoc)
* #see android.app.Activity#onCreate(android.os.Bundle)
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageView ARImage = new ImageView(getApplicationContext());
ARImage.setImageResource(R.drawable.icon);
RelativeLayout rl = new RelativeLayout(this);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int w = display.getWidth();
int h = display.getHeight();
RelativeLayout.LayoutParams position = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
ARImage.setLayoutParams(position);
position.addRule(RelativeLayout.CENTER_IN_PARENT);
rl.addView(ARImage, position);
setContentView(rl);
}
}
Try to use
position.leftMargin = (int)(w/2 - whalf);
position.topMargin = (int)(h/2 - hhalf);
where whalf and hhalf are halfs of your image parameters.
I don't think you can set the left and top margin like that:
position.leftMargin = (int)(w/2);
position.topMargin = (int)(h/2);
Try setting the margins like this:
position.setMargins((int)(w/2), (int)(h/2), 0, 0); // left, top, right, bottom
Knowing that it is inside of RelativeLayout, you can place it in center of this layout:
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
rl.addView(ARImage, lp);

Android Views Are Not As Tall As Specified

I am using RelativeLayout to position views at precise locations on the screen. This works as expected when using a view that say, draws a rectangle. But when using Android views like EditText, they are drawn shorter than specified by about 8 units. Clicking outside of the drawn EditText (but within the parameters specified by RelativeLayout) will, in fact, hit the EditText.
Here is some code to illustrate what I mean:
package com.DrawDemo;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.RelativeLayout;
public class DrawDemo extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout l = new RelativeLayout(this);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(100,100);
lp.leftMargin = 50;
lp.topMargin = 50;
DemoView demoview = new DemoView(this);
l.addView(demoview, lp);
EditText editText = new EditText(this);
l.addView(editText, lp);
setContentView(l);
}
private class DemoView extends View
{
public DemoView(Context context)
{
super(context);
}
#Override protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawPaint(paint);
}
}
}
If you execute this, you will notice that the EditText is noticeably shorter than the rectangle. I've tried mucking with onMeasure, setMinimumXXX, and just about everything else I can think of. So far, the only thing that works with some level of success is to just add 8 or so pixels to the height (8 seems to work better than trying a percentage of the height).
Next task will be to step into the source but was wondering if somebody has already solved this.
Thanks.
It's just because of the actual EditText background image that's used. Buttons are the same way, for some reason Google decided to draw the 9-patch background images with some extra transparent padding pixels. Really, the only solution, if it's a problem, would be to draw your own 9-patch, or modify the existing Android 9-patch to remove the extra pixels.

Categories

Resources