Alright. So I start my activity in Main, grab the FragmentManager and instantiate a Fragment which needs to return a View. OK. So I extended a LinearLayout in order to have something to return. My Activity and Fragment are happy but I am not.
Three LinearLayouts which I create in the parent ViewGroup are there (code below). I have verified this by counting children and by setting the background colors to contrast one another. The parent also changes size depending on how tall I make the children (when I don't declare any LayoutParams on the parent).
public class Mainmenu extends LinearLayout {
private ArrayList<LinearLayout> panes = new ArrayList<LinearLayout>();
private Context context;
private final int
LEFT = 0, CENTER = 1, RIGHT = 2;
public Mainmenu(Context c) {
super(c);
context = c;
setBackgroundColor(Color.WHITE);
setOrientation(HORIZONTAL);
setLayoutParams(
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
for(int i=0;i<=RIGHT;i++){ //Create the (3) Panes
LinearLayout ll = new LinearLayout(context);
ll.setLayoutParams(
new LinearLayout.LayoutParams(300,
LinearLayout.LayoutParams.FILL_PARENT));
switch(i){
case LEFT | RIGHT:
ll.setBackgroundColor(Color.DKGRAY);
default:
ll.setBackgroundColor(Color.BLACK);
}
ll.setOrientation(LinearLayout.VERTICAL);
ll.setVisibility(VISIBLE);
ll.setWillNotDraw(false);
panes.add(i, ll);
addView(ll);
}
LinearLayout.LayoutParams buttons =
new LinearLayout.LayoutParams(100, 50);
buttons.setMargins(15, 5, 5, 0);
TextView tv1 = new TextView(context);
tv1.setText("hello");
tv1.setTextColor(Color.RED);
panes.get(LEFT).addView(tv1, buttons);
Button button = new Button(context);
button.setText("Launch Editor");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
}
});
panes.get(CENTER).addView(button);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
Nothing is null, all my elements (3 ViewGroups and 2 Views) are present in the tree but not visible. I've tried bringing children to the front through the parent and the children, creating them in different super.methods and invalidating the view in a similarly shotgunned fashion. What's going on? Is it as simple as not having any idea what I'm doing?
The problem is simply because you are overriding onLayout and doing nothing with it. You only need to override this if you want to layout the children yourself (ie, you were designing some unique custom layout). In this case just remove that method, or call super.onLayout.
Related
I'm trying to create a view that contains TextView (on the left) and Button (on the right) and a SeekBar at the Bottom, something like this.
|-----------------------------------|
| <TextView> <Button> |
| < SeekBar > |
|-----------------------------------|
Note that angle brackets represents the width, just used for demonstration.
I can do that by creating a CompoundView but I wanted to keep things flat.
I'm going to create others similar to this one and there will be a lot of these.
Please ask for any further clarifications (if needed).
Thank you.
What about using a Framelayout and adding your views on the go?
public class Cell extends FrameLayout {
private TextView tv;
private Button btn;
private ProgressBar progressBar;
public Cell (Context context, int width, int height) {
super(context);
getLayoutParams().width = width;
getLayoutParams().height = height;
tv = new TextView(context);
FrameLayout.LayoutParams tvParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.TOP|Gravity.LEFT);
tv.setLayoutParams(tvParams);
btn = new Button(context);
FrameLayout.LayoutParams btnParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.TOP|Gravity.RIGHT);
btn.setLayoutParams(btnParams);
progressBar = new ProgressBar(context);
FrameLayout.LayoutParams progressParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM);
progressBar.setLayoutParams(progressParams);
addView(tv);
addView(btn);
addView(progressBar);
}
public void setText (String text) {
tv.setText(text);
}
public void setProgress (int progress) {
progressBar.setProgress(progress);
}
}
Note that you might need to use other constructors as well.
I want to generate Control dynamically by user specific value.
Like i have EditText for ControlId, Control Width, Control Height etc.
based on that value i want to generate control
LinearLayout L1 = new LinearLayout(this);
L1.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams L1paeam = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
L1.setLayoutParams(L1paeam);
TextView T1 = new TextView(this);
T1.setText(R.string.Dynamic_text);
L1.addView(T1);
Button B1=new Button(this);
B1.setText("Dynamic Button");
L1.addView(B1);
setContentView(L1);
In this code the control-id Layout_height and Layout_width are specified but i want them as user specified
You can add any View in view container (LinearLayout, RelativeLayout, etc) and remove those views in runtime. Create view and specify layout params for that view.
Here the solution i found.
public void generateButton(String Id,int Width,int Height,String text){
#IdRes
int id = Integer.parseInt(Id);
LinearLayout.LayoutParams L1param = new LinearLayout.LayoutParams(Width, Height);
final Button B1=new Button(this);
B1.setId(id);
B1.setText(text);
B1.setLayoutParams(L1param);
B1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Button click operation goes here
}
});
layout_main.addView(B1);
}
I want to parse text, and create for each word - button, but i don't know how to arrange them one after the other
String s = "Alice was beginning to get very tired of sitting";
String[] q = s.split(" ");
for (int i = 0; i < q.length; i++) {
Button myButton = new Button(this);
myButton.setText(q[i]);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.layout1);
layout.addView(myButton, params);
}
See this custom library: FlowLayout
While you're adding views inside FlowLayout, it automatically wraps when there is no space for the next item.
There's not much wrong about your approach, it's only that relative layout as name suggests requires child views to have some parameters to align the views relative to them e.g. above, below etc. As a result you are getting views overlapping each other and hence only the last added view is visible being on top.
Use FlowLayout instead and you'll be fine.
You need to define RelativeLayout parameters as in example below
Heres an example to get you started, fill in the rest as applicable:
TextView tv = new TextView(mContext);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
params.leftMargin = 107
...
mRelativeLayout.addView(tv, params);
The docs for RelativeLayout.LayoutParams and the constructors are
here
From: How to add a view programmattically to RelativeLayout?
Check the link below to get more useful informations.
Hope it will help
In the following code, you should change the upper limits of the for, to a variable.
public class MainActivity
extends Activity
implements View.OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TableLayout layout = new TableLayout (this);
layout.setLayoutParams( new TableLayout.LayoutParams(4,5) );
layout.setPadding(1,1,1,1);
for (int f=0; f<=13; f++) {
TableRow tr = new TableRow(this);
for (int c=0; c<=9; c++) {
Button b = new Button (this);
b.setText(""+f+c);
b.setTextSize(10.0f);
b.setTextColor(Color.rgb( 100, 200, 200));
b.setOnClickListener(this);
tr.addView(b, 30,30);
} // for
layout.addView(tr);
} // for
super.setContentView(layout);
} // ()
public void onClick(View view) {
((Button) view).setText("*");
((Button) view).setEnabled(false);
}
} // class
I am trying to initialize all the navigation bar buttons and assign Black background color, when user clicks on one of the button, that one should change color and all other should remain Black.
But i get the following error:
Attempt to invoke virtual method 'android.view.View android.widget.LinearLayout.getChildAt(int)' on a null object
reference
public void bottomNavIcons(View view){
for(int i=0;i<Constants.bottom_nav_icon.length;i++) {
LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.bottom_nav_bar);
ImageButton imageButton = new ImageButton(getActivity());
imageButton.setClickable(true);
imageButton.setOnClickListener(onClickListener);
imageButton.setImageResource(Constants.bottom_nav_icon[i]);
imageButton.setBackgroundColor(Color.BLACK);
imageButton.setPadding(70, 0, 70, 0);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
linearLayout.addView(imageButton, layoutParams);
}
}
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout linearLayout = (LinearLayout) v.findViewById(R.id.bottom_nav_bar);
for(int i=0;i<Constants.bottom_nav_icon.length;i++) {
ImageView imageButton = (ImageView) linearLayout.getChildAt(i);
imageButton.setBackgroundColor(Color.BLACK);
}
v.setBackgroundColor(Color.BLUE);
}
};
I think this is the problem:
LinearLayout linearLayout = (LinearLayout) v.findViewById(R.id.bottom_nav_bar);
You are assuming the LinearLayout is inside the view which is clicked - my best guess is this is not true (you probably want to get the clicked view's parent, not child).
You have 2 options:
Start iterating the view hierarchy to the top (i.e. call v.getParent()) until you reach the LinearLayout.
Call findViewById on the containing activity (or fragment's root view) instead of the v object.
How can we add buttons at dynamic positions in layout or using canvas, not in table layout?
Can anyone please help me on this?
Use RelativeLayout to position your controls where you like them. Have a look at this link:
Dynamic TextView in Relative layout
and here
How to create a RelativeLayout programmatically with two buttons one on top of the other?
If you like to achieve it within XML only. Look here:
http://www.mkyong.com/android/android-relativelayout-example/
Here an example how you could use the RelativeLayout to position your controls dynamically:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Creating a new RelativeLayout
RelativeLayout mainRelativeLayout = new RelativeLayout(this);
// Defining the RelativeLayout layout parameters with Fill_Parent
RelativeLayout.LayoutParams relativeLayoutParameters = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.FILL_PARENT);
// Creating a new Left Button
Button buttonLeft = new Button(this);
buttonLeft.setText("Left");
// Creating a new Left Button with Margin
Button buttonLeftWithMargin = new Button(this);
buttonLeftWithMargin.setText("Left with Margin");
// Creating a new Center Button
Button buttonCenterParent = new Button(this);
buttonCenterParent.setText("Center");
// Creating a new Bottom Button
Button buttonBottom = new Button(this);
buttonBottom.setText("Bottom");
// Add a Layout to the Buttons
AddButtonLayout(buttonLeft, RelativeLayout.ALIGN_PARENT_LEFT);
AddButtonLayout(buttonCenterParent, RelativeLayout.CENTER_IN_PARENT);
AddButtonLayout(buttonBottom, RelativeLayout.ALIGN_PARENT_BOTTOM);
// Add a Layout to the Button with Margin
AddButtonLayout(buttonLeftWithMargin, RelativeLayout.ALIGN_PARENT_LEFT, 30, 80, 0, 0);
// Add the Buttons to the View
mainRelativeLayout.addView(buttonLeft);
mainRelativeLayout.addView(buttonCenterParent);
mainRelativeLayout.addView(buttonBottom);
mainRelativeLayout.addView(buttonLeftWithMargin);
// Setting the RelativeLayout as our content view
setContentView(mainRelativeLayout, relativeLayoutParameters);
}
private void AddButtonLayout(Button button, int centerInParent, int marginLeft, int marginTop, int marginRight, int marginBottom) {
// Defining the layout parameters of the Button
RelativeLayout.LayoutParams buttonLayoutParameters = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
// Add Margin to the LayoutParameters
buttonLayoutParameters.setMargins(marginLeft, marginTop, marginRight, marginBottom);
// Add Rule to Layout
buttonLayoutParameters.addRule(centerInParent);
// Setting the parameters on the Button
button.setLayoutParams(buttonLayoutParameters);
}
private void AddButtonLayout(Button button, int centerInParent) {
// Just call the other AddButtonLayout Method with Margin 0
AddButtonLayout(button, centerInParent, 0 ,0 ,0 ,0);
}
}
And you should get something like this: