How to center text vertically in a TextView with Java code? - java

I know this question has been asked many times on SO. I have read most of them, but they don't work for me, so don't bother marking duplicates.
Here is my code, and what I have tried so far:
RelativeLayout container = new RelativeLayout(this.getContext());
TextView tv = new TextView(this.getContext());
tv.setText(txt); // a single digit like '3'
tv.setLines(1);
tv.layout(0, offsety, cellszie, offsety+cellsize);
tv.setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);
tv.setGravity(Gravity.CENTER);
// I also tried CENTER_VERTIAL and the following line
// tv.setGravity(CENTER_VERTIAL| CENTER_HORIZONTAL);
// I also tried giving LayoutParams to tv like this:
// tv.setLayoutParams(new LayoutParams(cellsize, cellsize));
// tv.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
// tv.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT));
container.addView(tv);
The character is horizontally centered, but it floats on the top of the TextView vertically. Setting gravity and LayoutParams doesn't change its behavior.
What should I do to make it center vertically?

use this class for VerticalTextView.
public class VerticalTextView extends TextView {
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs){
super(context, attrs);
final int gravity = getGravity();
if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
}else
topDown = true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}

you can do it like this
RelativeLayout container = new RelativeLayout(this.getContext());
View view = layoutInflater.inflate(R.layout.my_layout_file, null);
container.addView(view);
where R.layout.my_layout_file contains textview with gravity center. and here you can get object of textview like this
textviewObject = (TextView)view.findViewById(R.id.textViewId)

Try setting RelativeLayout.LayoutParams to you RelativeLayout
RelativeLayout.LayoutParams relativeLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
container.setLayoutParams(relativeLayoutParams)
Then set the gravity for your TextView:
tv.setGravity(Gravity.CENTER);
Then add the view to your RelativeLayout:
container.addView(tv);

Related

How to display label using Slider of Material component?

I am using the Slider of Material component:
https://github.com/material-components/material-components-android/blob/master/docs/components/Slider.md
I am trying to display a label when the thumb is moving, which seem to be supported with the labelFormatter attribute.
here is what my code looks like:
Slider s = new Slider(context);
s.setLabelFormatter(new Slider.LabelFormatter() {
#NonNull
#Override
public String getFormattedValue(float value) {
return "MY STRING";
}
});
When I go line by line with debugger it goes through this function:
private void drawLabelText(#NonNull Canvas canvas, int width, int top) {
labelTextPaint.getTextBounds(labelText, 0, labelText.length(), labelTextBounds);
int left = trackSidePadding + (int) (thumbPosition * width) - labelTextBounds.width() / 2;
canvas.drawText(labelText, left, top - labelTextTopOffset - thumbRadius, labelTextPaint); }
but no text is displayed only the slider...
I am kind of new in androïd and I am surely missing something.
Thanks for help :)
EDIT 1:
Here is the whole code simplified :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CoordinatorLayout layout = new CoordinatorLayout(this);
setContentView(layout);
// I am Using Coordinator Layout for current activity so...
CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//Setting gravity to CENTER
layoutParams.gravity = Gravity.CENTER;
Slider slider = new Slider(this);
slider.setLabelFormatter(new Slider.LabelFormatter() {
#NonNull
#Override
public String getFormattedValue(float value) {
return "MY STRING";
}
});
layout.addView(slider, layoutParams);
}
But still not working ...
output result
https://youtu.be/obV4K-Nxu-0
EDIT 2:
Updating Material component from version: '1.2.0-alpha02' to version: '1.2.0-alpha05' fixed the issue.
Actually i wanted to comment but because of Reputation Constraints i couldn't,
Looks like you are adding a view programatically in your activity. Here i have implemented new MaterialComponent Slider with LabelFormatter
ViewGroup group = findViewById("YOUR_ACTIVITY_LAYOUT");
// I am Using Coordinator Layout for current activity so...
CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//Setting gravity to CENTER
layoutParams.gravity = Gravity.CENTER;
Slider slider = new Slider(this);
slider.setLabelFormatter(new Slider.LabelFormatter() {
#NonNull
#Override
public String getFormattedValue(float value) {
return "MY STRING";
}
});
group.addView(slider, layoutParams);
}
And then there you go...

Null Pointer Exception - Setting the text of a TextView inside a programmatically created layout [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I am trying to set the text of a TextView. However, I am receiving the following error whenever I click a button that should add text to the TextView:
NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference" from the logcat.
Currently, the init() function programmatically creates/aligns the TextView inside a linearlayout. Next, I instantiate the TextView Whole1. Then I set the OnClickListener for the buttons that can modify the TextView. The specific line that the error mentions is inside setWholeOnClickListener():
Whole1.setText(button.getText());
I've found What is a NullPointerException, and how do I fix it? as a reference, but haven't had much luck resolving this issue. What did I miss?
The following is my Java file:
public class MainActivity extends AppCompatActivity {
TextView Whole1;
private boolean isNull = true;
private int[] wholeButtons = {R.id.wholeButton1, R.id.wholeButton2, R.id.wholeButton3, R.id.wholeButton4, R.id.wholeButton5, R.id.wholeButton6, R.id.wholeButton7, R.id.wholeButton8, R.id.wholeButton9, R.id.wholeButton0};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
Whole1 = (TextView) findViewById(R.id.Whole1);
setWholeOnClickListener();
}
private void setWholeOnClickListener() {
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Button button = (Button) v;
if (isNull) {
Whole1.setText(button.getText());
isNull = false;
} else {
Whole1.append(button.getText());
}
}
};
for (int id : wholeButtons) {
findViewById(id).setOnClickListener(listener);
}
}
/* Initializes the first view for input */
private void init() {
LinearLayout Result = (LinearLayout) findViewById(R.id.Result);
RelativeLayout Mixed = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.MATCH_PARENT);
Mixed.setLayoutParams(params);
TextView Whole1 = new TextView(this);
TextView Fraction1 = new TextView(this);
TextView Num1 = new TextView(this);
TextView Den1 = new TextView(this);
/* Scale is a screen dependent value, used for filling the screen */
final float scale = getResources().getDisplayMetrics().density;
int pixels = (int) (2 * scale + 0.5f);
/* Fraction bar 1 */
params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, pixels);
params.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
params.addRule(RelativeLayout.RIGHT_OF, Whole1.getId());
Fraction1.setBackgroundColor(Color.BLACK);
Fraction1.setText("________"); // Placeholder
Fraction1.setLayoutParams(params);
Mixed.addView(Fraction1);
/* Numerator 1 */
params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
params.addRule(RelativeLayout.ABOVE, Fraction1.getId());
Num1.setText("3");
Num1.setGravity(Gravity.CENTER);
Num1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
Num1.setLayoutParams(params);
Mixed.addView(Num1);
/* Denominator 1 */
params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
params.addRule(RelativeLayout.BELOW, Fraction1.getId());
Den1.setText("4");
Den1.setGravity(Gravity.CENTER);
Den1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
Den1.setLayoutParams(params);
Mixed.addView(Den1);
/* Whole 1 */
params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.MATCH_PARENT);
params.addRule(RelativeLayout.LEFT_OF, Num1.getId());
params.addRule(RelativeLayout.CENTER_VERTICAL);
Whole1.setGravity(Gravity.CENTER);
Whole1.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40);
Whole1.setLayoutParams(params);
Mixed.addView(Whole1);
Result.addView(Mixed);
Result.invalidate();
}
}
Whole1 = (TextView) findViewById(R.id.Whole1);
finds a TextView with the id R.id.Whole1 in the activity's layout.
You created a TextView programmatically, assigned it to your Whole1 variable, but then overwrote the variable with the new assignment Whole1 = (TextView) findViewById(R.id.Whole1);.
After that it's probably null because you dont have a TextView with that id in the layout XML that you inflated.

How to get ImageView ID from inflater in Android

I'm using an inflater to show a popup setting menu made by me. It's composed by some images and buttons. After complete XML layout I'm started to code it, it opens correctly with this code:
public void Settings_button(View view)
{
if (p != null)
showPopup(Main_activity.this, p);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
int[] location = new int[2];
ImageButton setting_button = (ImageButton) findViewById(R.id.settings_button);
// Get the x, y location and store it in the location[] array
// location[0] = x, location[1] = y.
setting_button.getLocationOnScreen(location);
//Initialize the Point with x, and y positions
p = new Point();
p.x = location[0];
p.y = location[1];
}
// The method that displays the popup.
private void showPopup(final Activity context, Point p) {
Resources r = getResources();
int popupWidth = 500;
int popupHeight = 300;
// Inflate the popup_layout.xml
LinearLayout viewGroup = (LinearLayout) context.findViewById(R.id.popup);
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate(R.layout.settings_popup_layout, viewGroup);
// Creating the PopupWindow
final PopupWindow popup = new PopupWindow(context);
popup.setContentView(layout);
popup.setWidth(popupWidth);
popup.setHeight(popupHeight);
popup.setFocusable(true);
// Some offset to align the popup a bit to the right, and a bit down, relative to button's position.
int OFFSET_X = 150;
int OFFSET_Y = 30;
// Displaying the popup at the specified location, + offsets.
popup.showAtLocation(layout, Gravity.NO_GRAVITY, p.x + OFFSET_X, p.y + OFFSET_Y);
}
But now I need to get ImageViews IDs and Buttons IDs, I've used:
//In onCreate of Main_Activity
ImageView popup_setting_1_icon;
popup_setting_1_icon = (ImageView) findViewById(R.id.setting_1_icon);
Button popup_setting_1_button;
popup_setting_1_button = (Button) findViewById(R.id.setting_1_button);
But when I'm starting to use this Views for example popup_setting_1_icon.setImageResource(R.id.setting_done_icon); I get application crash with NullPointerException.
I've read something like I should get pointers from inflater but I've tried to do so inside showPopup method but nothing. How I can solve this problem?
Initialize views in show popup method:
ImageView popup_setting_1_icon;
popup_setting_1_icon = (ImageView)layout. findViewById(R.id.setting_1_icon);
Button popup_setting_1_button;
popup_setting_1_button = (Button)layout. findViewById(R.id.setting_1_button);
I had a very similar problem with programmatically inflating a container and populating it. This is what worked for me:
LayoutInflater inflator = LayoutInflater.from(getContext());
LinearLayout viewGroup = (LinearLayout) getActivity().findViewById(
R.id.popup);
View layout = inflator.inflate(R.layout.settings_popup_layout, null);
Button button = (Button) layout.findViewById(R.id.setting_1_button);
ImageView image = (ImageView) layout.findViewById(R.id.setting_1_icon);
//bind data to view/buttons
viewGroup.addView(layout);
This is assuming your settings button and image views are inside the settings popup layout.

Programmatically Center LinearLayout within another LinearLayout

I need to place two TextViews side by side inside a centered view.
I tried asking a similar question yesterday, only with relative layouts. I've made a lot of progress since switching to linear layout for the parent of the two TextViews, so I'd like to see if anyone can add the final component.
Here's what I have:
public void addTableLink(String s, String s1, int g, LinearLayout L, int fsize, int textColor, int backgroundColor, int lpad, int tpad, final String section, final String selection){
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setGravity(Gravity.CENTER_VERTICAL);
ll.setLayoutParams(new LinearLayout.LayoutParams(400, 30, Gravity.CENTER_HORIZONTAL));
ll.setBackgroundColor(backgroundColor);
TextView tv1 = new TextView(this);
TextView tv2 = new TextView(this);
tv1.setText(s);
tv2.setText(s1);
tv1.setTextSize(fsize);
tv2.setTextSize(fsize);
tv1.setTextColor(textColor);
tv1.setTextColor(textColor);
ll.addView(tv1);
ll.addView(tv2);
L.addView(ll);
}
Which gives me this:
All I need now is to get that "Company: Google" section (the white part) to be centered above, while keeping the text left aligned.
Any suggestions?
Solved it. Here's the code, all you need to do is center the view that is passed to this method (LinearLayout L) and it works great (the secret is setting the new view to horizontal):
public void addTableLink(String s, String s1, int g, LinearLayout L, int fsize, int textColor, int backgroundColor, int lpad, int tpad, final String section, final String selection){
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setGravity(Gravity.CENTER_VERTICAL);
ll.setLayoutParams(new LinearLayout.LayoutParams(400, 30));
ll.setBackgroundColor(backgroundColor);
TextView tv1 = new TextView(this);
TextView tv2 = new TextView(this);
tv1.setText(s);
tv2.setText(s1);
tv1.setPadding(lpad, tpad, 0, 0);
tv1.setTextSize(fsize);
tv2.setTextSize(fsize);
tv1.setTextColor(textColor);
tv2.setTextColor(Color.BLUE);
tv2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setMainView(section, selection);
setTitle(section);
}
});
ll.addView(tv1);
ll.addView(tv2);
L.addView(ll);
}

Scroll TextView to text position

I want to scroll my TextView to make visible a specific position in the text. How can I do that? I tried bringPointIntoView (int offset) but without success.
Source code:
public class TextScrollActivity extends Activity {
public void onCreate (final Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
final int position = 500;
final TextView textView = new TextView (this);
final ScrollView scrollView = new ScrollView (this);
scrollView.addView (textView);
Button button = new Button (this);
button.setText ("Scroll to " + position);
LinearLayout layout = new LinearLayout (this);
layout.setOrientation (LinearLayout.VERTICAL);
layout.addView (scrollView,
new LayoutParams (LayoutParams.FILL_PARENT, 200));
layout.addView (button, new LayoutParams (LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
StringBuilder builder = new StringBuilder ();
for (int i = 0; i < 1000; i++)
builder.append (String.format ("[ %05d ] ", i));
textView.setText (builder);
setContentView (layout);
button.setOnClickListener (new OnClickListener () {
public void onClick (View v) {
System.out.println (textView.bringPointIntoView (position * 10));
// scrollView.scrollTo (0, position * 10); // no
}
});
}
}
For those who have the same problem, I finally made my own implementation of bringPointIntoView:
public static void bringPointIntoView (TextView textView,
ScrollView scrollView, int offset)
{
int line = textView.getLayout ().getLineForOffset (offset);
int y = (int) ((line + 0.5) * textView.getLineHeight ());
scrollView.smoothScrollTo (0, y - scrollView.getHeight () / 2);
}
Don't hesitate if you have a better solution.
Does adding a movement method to the text view solve the problem?
textView.setMovementMethod(new ScrollingMovementMethod());
Just FYI for anyone else with the same problem, on a listView with large listItems, the overloaded bringPointIntoView can be passed a ListView instead of a ScrollView and use the ScrollTo method instead of smoothScrollTo.

Categories

Resources