Programmatically Adding EditText with weight - java

I've created a Vertical LinearLayout with a Horizontal LinearLayout within it in order to hold 3 EditText boxes within them for data entry. I've also placed a button below the vertical LinearLayout that I want to program to add another row of editText with every press.
I've succeeded so far and managed to programmatically add another row with 1 edittext in it. Then I tried with 3 and hit a roadblock. I tried to use weightsum and weights to get the editText boxes to be in 3 columns. However with the code below I get 2 editText boxes next to each other then a very very tiny editbox as the last one.
What am I doing wrong? Why aren't the widths of the edittext boxes being divided by 3?
XML:
<LinearLayout android:id="#+id/layout_ingredients"
android:layout_below="#id/text_recipeIngredients"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="3"
android:orientation="horizontal">
<EditText android:id="#+id/edit_recipeIngredient"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="#string/edit_recipe_ingredient"/>
<EditText android:id="#+id/edit_recipeAmount"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="#string/edit_recipe_amount"/>
<EditText android:id="#+id/edit_recipeUnit"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="#string/edit_recipe_unit"/>
</LinearLayout>
</LinearLayout>
<Button android:id="#+id/btn_add_ingredient"
android:background="#color/orange"
android:layout_marginTop="10dp"
android:layout_below="#id/layout_ingredients"
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="#string/btn_add_ingredient"
android:onClick="addIngredients"/>
Java:
public void addIngredients(View view) {
final String ADDINGREDIENT = "ADD INGREDIENT";
Log.d(ADDINGREDIENT, ADDINGREDIENT);
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.layout_ingredients);
LinearLayout ingredientLayout = new LinearLayout(this);
ingredientLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
ingredientLayout.setOrientation(LinearLayout.HORIZONTAL);
ingredientLayout.setWeightSum(3f);
EditText editTextIngredient = new EditText(this);
editTextIngredient.setHint("Ingredient");
editTextIngredient.setLayoutParams(new LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.WRAP_CONTENT,
1f));
EditText editTextAmount = new EditText(this);
editTextAmount.setHint("Amount");
editTextAmount.setLayoutParams(new LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.WRAP_CONTENT,
1f));
EditText editTextUnit = new EditText(this);
editTextAmount.setHint("Unit");
editTextAmount.setLayoutParams(new LinearLayout.LayoutParams(
0,
LinearLayout.LayoutParams.WRAP_CONTENT,
1f));
ingredientLayout.addView(editTextIngredient);
ingredientLayout.addView(editTextAmount);
ingredientLayout.addView(editTextUnit);
linearLayout.addView(ingredientLayout);
}

The problem here is that you are adding the weighted layouts to a layout that is not on the screen, so its width is unknown at the time you add them.
You have a couple of approaches, but the easiest one is probably to grab the widths of the elements already on the screen and simply duplicate them (since you are using a weighted layout to begin with).
You could also measure the screen and use that measurement to set the widths of each layout.
Last, you could use ViewTreeObserver to add them after the parent has been added and the width is known (see the post here: Getting the width/height of a layout in Android).
The last is the most "interesting" but the least efficient and useful since your original layout already did the calculations.

Related

How to make Android EditText force its container to scroll

I have an Android app which can create multiple lines each of which contains two spinners and an EditText. If the content gets too wide for the EditText, it breaks into multiple lines and this messes up my layout. So I call setMaxLines(1). But now the EditText scrolls internally. I want the EditText to expand horizontally to fit its content and the containing HorizontalScrollView to scroll. How can I do this?
I tried putting a HorizontalScrollView in a ScrollView and vice versa. Neither way round works. I expected that setting (both) LayoutParams to wrap_content would work but it doesn't.
I haven't included all of the code because it is a big app. Here is the layout XML:-
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- This is an invisible view to request the focus when an EditText gets deleted
in order to stop Android highlighting something else.
It would be nicer to go back into touch mode,
but Android does not provide a way of doing that. -->
<TextView
android:layout_width="1dp"
android:layout_height="1dp"
android:text=""
android:alpha="0"
android:id="#+id/defineinvisible"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/defineclasslayout">
</LinearLayout>
</LinearLayout>
</ScrollView>
</HorizontalScrollView>
The lines containing the EditTexts are added dynamically because the number of them can vary as the app runs.
The code to add a line looks a bit like this (I've left out some irrelevant detail):-
public class OrItem extends LinearLayout implements TextWatcher {
public OrItem(Context context) {
m_nameSelector = new Spinner(m_context);
m_contSelector = new Spinner(m_context);
m_matchString = new EditText(m_context);
m_matchString.setHorizontallyScrolling(false); m_matchString.setMaxLines(1);
m_matchString.setInputType(TYPE_CLASS_TEXT);
}
public setup(...) {
ViewGroup.LayoutParams ww = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
setOrientation(LinearLayout.HORIZONTAL);
addView(m_nameSelector, ww);
addView(m_contSelector, ww);
m_matchString.setText(sa[2]);
m_wasEmpty = sa[2].isEmpty();
m_matchString.addTextChangedListener(this);
addView(m_matchString, ww);
}
}
The OrItem is added under a hierarchy of LinearLayouts that hangs from defineclasslayout.
I tried inserting
but this goes back to line wrapping inside the EditText.
I found workaround for this. I make each individual line a HorizontalScrollView. Then I can scroll a long line. This is less elegant than scrolling the whole view, but it works.
public class OrItem extends HorizontalScrollView implements TextWatcher {
public OrItem(Context context) {
m_layout = new LinearLayout(context);
m_nameSelector = new Spinner(context);
m_contSelector = new Spinner(context);
m_matchString = new EditText(context);
m_matchString.setMaxLines(1);
m_matchString.setInputType(TYPE_CLASS_TEXT);
m_matchString.setHorizontallyScrolling(false);
}
public boolean setup(...) {
ViewGroup.LayoutParams ww = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
addView(m_layout);
m_layout.setOrientation(LinearLayout.HORIZONTAL);
m_layout.addView(m_nameSelector, ww);
m_layout.addView(m_contSelector, ww);
m_matchString.addTextChangedListener(this);
m_layout.addView(m_matchString, ww);
}

Horizontal scroll and focus on the last number in a TextView

I am doing a calculator app.
I have a TextView where the user writes the numbers to elaborate.
The TextView is inside a HorizontalScrollView. The HorizontalScrollView is inside a vertical LinearLayout. The TextView is single line, and, when the user writes a long number, the number comes out of the screen.
The TextView should follow the last number added by the user, so he can view the last numbers added without scrolling the screen. I don't want an autoscroll function that repeat the scroll every second, i only want focus on the last number added.
This is the TextView
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/numberDisplay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginTop="16dp"
android:hint="0"
android:scrollHorizontally="true"
android:maxLines="1"
android:layout_gravity="right"
android:textSize="70sp" />
</HorizontalScrollView>
Try this:
In your activity create variables for your scroll view and text view:
TextView textView;
HorizontalScrollView scrollView;
Initialize them in onCreate():
scrollView = (HorizontalScrollView) findViewById(R.id.scrollView); // Add this id to xml
textView = (TextView) findViewById(R.id.numberDisplay);
Each time you update text of your text view update scroll position of the scroll view:
scrollView.scrollTo(textView.getRight(), textView.getTop());
Update:
I realized that if you call textView.setText(...) and then immediately scrollView.scrollTo(...) it does not work since text view size is not updated immediately. You should rather update scoll position like this:
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.scrollTo(textView.getRight(), textView.getTop());
}
});

Dynamically adding buttons next to each other - RelativeLayout

Ok, so here's the thing. I'm trying to make an app that resembles a piano for android, also I've never really had much experience with Java or programming for Android so all of this is pretty new to me. I've managed to do this in XML but I want to make it programmaticaly so I can easily add more white and black keys also dependant of screen size. In XML it looks like this
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/white1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white2"
android:layout_toRightOf="#+id/white1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white3"
android:layout_toRightOf="#+id/white2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white4"
android:layout_toRightOf="#+id/white3"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white5"
android:layout_toRightOf="#+id/white4"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white6"
android:layout_toRightOf="#+id/white5"/>
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#fff"
android:id="#+id/white7"
android:layout_toRightOf="#+id/white6"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginStart="-10dp"
android:layout_marginEnd="-6dp"
android:background="#000"
android:id="#+id/black1"
android:layout_toRightOf="#+id/white1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginLeft="-6dp"
android:layout_marginRight="-10dp"
android:background="#000"
android:id="#+id/black2"
android:layout_toRightOf="#+id/white2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginLeft="-10dp"
android:layout_marginRight="-6dp"
android:background="#000"
android:id="#+id/black3"
android:layout_toRightOf="#+id/white4"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginLeft="-8dp"
android:layout_marginRight="-8dp"
android:background="#000"
android:id="#+id/black4"
android:layout_toRightOf="#+id/white5"/>
<Button
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_marginLeft="-6dp"
android:layout_marginRight="-10dp"
android:background="#000"
android:id="#+id/black5"
android:layout_toRightOf="#+id/white6"/>
And now I wanted to recreate it programmaticaly, at first I've tried linear approach but first of all I was unable to make more than 7 keys, and I didn't really knew how to make black keys on top of that. So now I've went with RelativeLayout and all is fine as long as I create two buttons, then it works fine, one is next to another. But when I try to create more than two buttons they kinda make a stack.
I was trying to make some sort of array of buttons so I could easily make a loop to create destined number of buttons. Also I wanted to change the width of buttons, so if I create 8 buttons the would have the width of screen_width/8 but I'm not quite sure if it makes any sense since it's actually not doing anything when uncommented.
I would be grateful for any tips :)
public class MainActivity extends AppCompatActivity {
final int[] whitelist = {R.id.whitebt1,R.id.whitebt2,R.id.whitebt3,R.id.whitebt4,R.id.whitebt5,
R.id.whitebt6,R.id.whitebt7,R.id.whitebt8};
Button[] whiteKeys = new Button[whitelist.length];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
final RelativeLayout pianoLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams whiteKeyParams1 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
whiteKeys[0] = new Button(this);
whiteKeys[0].setId(View.generateViewId());
//whiteKeys[0].setHeight(height);
//whiteKeys[0].setWidth(width/8);
whiteKeys[0].setLayoutParams(whiteKeyParams1);
pianoLayout.addView(whiteKeys[0]);
whiteKeys[1] = new Button(this);
whiteKeys[1].setId(View.generateViewId());
//whiteKeys[i].setHeight(height);
RelativeLayout.LayoutParams whiteKeyParams2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
whiteKeyParams2.addRule(RelativeLayout.RIGHT_OF, whiteKeys[0].getId() );
whiteKeys[1].setLayoutParams(whiteKeyParams2);
pianoLayout.addView(whiteKeys[1]);
//HERE'S IS THE MOMENT WHERE I TRY TO ADD THIRD BUTTON AND THE BUTTONS START TO PILE UP
/*
whiteKeys[2] = new Button(this);
whiteKeys[2].setId(View.generateViewId());
//whiteKeys[i].setHeight(height);
//RelativeLayout.LayoutParams whiteKeyParams2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
whiteKeyParams2.addRule(RelativeLayout.END_OF, whiteKeys[1].getId());
whiteKeys[2].setLayoutParams(whiteKeyParams2);
pianoLayout.addView(whiteKeys[2]);*/
this.setContentView(pianoLayout);
}
}
You can add 8 same size buttons using weightsum and layoutweight with LienarLayout with horizontal orientations.
see below code it may help you to add same size buttons dynamically.
/* Add a new Linearlayout as a container for the buttons */
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
//Added Weight Sum 8 in LinearLayout
linearLayout.setWeightSum(8);
/* Create a new Buttons in this container, for the status bar */
//below LayoutParams define with weight 1 for buttons.
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f);
Button button1 = new Button(linearLayout.getContext());
button1.setLayoutParams(param);
Button button2 = new Button(linearLayout.getContext());
button2.setLayoutParams(param);
Button button3 = new Button(linearLayout.getContext());
button3.setLayoutParams(param);
Button button4 = new Button(linearLayout.getContext());
button4.setLayoutParams(param);
Button button5 = new Button(linearLayout.getContext());
button5.setLayoutParams(param);
Button button6 = new Button(linearLayout.getContext());
button6.setLayoutParams(param);
Button button7 = new Button(linearLayout.getContext());
button7.setLayoutParams(param);
Button button8 = new Button(linearLayout.getContext());
button8.setLayoutParams(param);
With your approach before adding the view to parent layout you will have to add margins for every new key also which will prevent stacking one key over another.
params.setMargins(left, top, right, bottom);

How to write Text on ImageView in android coding?

Hi I've been trying to write Numbers on Imageview. Images for N number of questions. If the user entered answer is correct, then it should be displayed with question number with tick mark image else question number with wrong mark image. I need to write the question number on the image. My code is here:
LinearLayout l_layout = (LinearLayout) findViewById(R.id.linear_view_report);
LayoutParams param = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
ImageView[] imgview=new ImageView[questions.length];
for(int i=0;i<no_of_questions;i++)
{
if(userEnteredAnswers[i]==correct_answer[i]){
Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.correct);
Canvas canvas = new Canvas(bm);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(10);
canvas.drawText(i, 5, 5, paint);
imgview[i]=new ImageView(this);
imgview[i].setImageDrawable(new BitmapDrawable(bm));
l_layout.addView(imgview[i]);
}
else {
Bitmap bm=BitmapFactory.decodeResource(getResources(),R.drawable.wrong);
Canvas canvas = new Canvas(bm);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(10);
canvas.drawText(i, 5, 5, paint);
imgview[i]=new ImageView(this);
imgview[i].setImageDrawable(new BitmapDrawable(bm));
l_layout.addView(imgview[i]);
}
}
I get this warning:
The constructor BitmapDrawable(Bitmap) is deprecated
Image doesn't showing at run time.
What am I doing wrong?
I believe the easiest workaround without overriding anything would be to have a TextView and set its background with a drawable resource.
For instance:
TextView t = (TextView)findViewById(R.id.my_text_view);
// setting gravity to "center"
t.setGravity(Gravity.CENTER);
t.setBackgroundResource(R.drawable.my_drawable);
t.setText("FOO");
From the Android documentation :
BitmapDrawable(Bitmap bitmap)
This constructor was deprecated in API level 4. Use BitmapDrawable(Resources, Bitmap) to ensure that the drawable has correctly set its target density.
You can also create your own view (see Android: Creating Custom Views tutorial for an example) and put you image and the text in this view.
1). Make your own layout Say Image_TextView.xml like this :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="150dp"
android:layout_height="150dp"
android:gravity="center" >
<ImageView
android:id="#+id/imgview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:cropToPadding="true"
android:scaleType="center"
android:src="#drawable/box" />
<RelativeLayout
android:layout_width="150dp"
android:layout_height="35dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="0dp"
android:background="#80666666" >
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Hello"
android:textColor="#FFFFFF"
android:textStyle="bold"/>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
This will make Image with Text over it.
2). Then use layout inflator to inflate this view in your parent view.
Note : Using layout inflator you can add other view to your parent view.
its not possible to write text on imageview, but you can extend it to do so. Alternatively,
you can add an element overlapping the ImageView in the layout, and make it visible only when your condition becomes true.
or, you can use textView to display image, as a background or as a drawable to left/right..
Ps: however, the option 1 is easier to implement, but it will have additional rendering. so consider the other option first.

Add TextView on top of Button?

I'm building a contacts app which displays big contact photos. I need to add a label with the contacts name of each contact on top of the button (near the bottom) however I don't know how to get two views on top of each other. I cannot simply use settext since I need to add a semi-transparent background to the label.
EDIT:
I managed to get it on top but I cannot figure out how to get it on the bottom of the button.
RelativeLayout icon = new RelativeLayout(context);
// Create button
Button button = new Button(context);
button.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
layout.addView(button);
// Create label
TextView label = new TextView(context);
label.setText(name);
label.setBackgroundColor(Color.argb(120, 0, 0, 0));
label.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
icon.addView(button);
icon.addView(label);
However the text appears on the top of the image and I want it to be on the bottom like this:
With xml this would be something like: android:layout_alignBottom="#+id/myButton" but I'm doing this programatically and I haven't found a way to do it. How can I place my label near the button?
Try this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" >
<Button
android:id="#+id/button1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="right"
android:text="John"
android:background="#drawable/button_action_active" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="test textView" />
</FrameLayout>
</LinearLayout>
Dynamically you can do by
TextView lable = new TextView(this);
lable.setLayoutParams(new LayoutParams(android.widget.LinearLayout.LayoutParams.WRAP_CONTENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT));
lable.setTextSize(25);
lable.setGravity(Gravity.CENTER);
lable.setText("John");
Button button = new Button(this);
button.setBackgroundResource(R.drawable.button_action_active);
button.setLayoutParams(new LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT));
FrameLayout fl = new FrameLayout(this);
fl.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
fl.addView(button);
fl.addView(lable);
setContentView(fl);
To do this you can use a frame layout. The documentation for frame layout can be found here - http://developer.android.com/reference/android/widget/FrameLayout.html
However, frame layout is depreciated (if I remember correctly). So instead I would recommend using a relative layout. In your relative layout you can set the position of the button and then give the textview the attributes android:layout_alignLeft=#id/somethingand android:layout_alignRight="#id/Something"

Categories

Resources