While loop causing activity screen to show nothing? - java

Whenever I make a while loop in an app for android, it causes my screen to show only the basic background & action bar. It was very frustrating when I found this in my app, and I've spent the past couple hours attempting to find a workaround. I've made a very basic program trying to narrow down the cause and found it to be the while loop, which leaves me with a blank screen.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Assign Variables
EditText editText_HEX = (EditText)findViewById(R.id.EditText_HEX);
String stringHEX = editText_HEX.getText().toString();
Boolean isHex = stringHEX.matches("^#([A-Fa-f0-9]{6})$");
// I have (true) in right now, but if I change that to a more specific boolean I still
// can't see the page of my app.
while (true){
// Here I'm trying to get the loop to pause until the user enters 7 characters
// into the EditText box.
// I've tried while (editText_HEX.length() < 7) as well, but still get a blank page
while (stringHEX.length() < 7){
}
Toast.makeText(getApplicationContext(), "text reached 7 characters", Toast.LENGTH_SHORT).show();
break;
}
}
I'm not getting any error in the logcat- the app works fine, it just doesn't show any of my widgets. If I delete the while loop, it works.
What I'm ultimately trying to get:
I'm trying to make an app that asks the user enter a hex value that will change the color of the background. In my previous question (which was answered), I figured out how to check for a valid hex. Now I want this loop running so that a person can enter a hex color into an EditText box, and the background color will instantly change; and if they re-enter a different hex into the textbox, the background will change once more. This while loop is just a simple program that I made to narrow down why my page was blank.
I've been working on different parts of an app in different projects. This is one- and then I'm planning on making the larger final app after I figure out the reasons for these errors and such. I'm new to programming for android, so if there is a simple fix to this I'd appreciate the help. Thanks!

Don't use a loop try this:
editText_HEX.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
// check for valid hex here
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
});

By default the length of the text in the stringHEX is 0. And in onCreate itself even before the layout is shown, you have a while loop which is checking the length of stringHEX. Since it becomes an infinite while loop, you are not getting anything on the screen. Just to test, give a dummy text to your stringHEX in your xml and it should work fine.

Related

How to put a delay between the initial ValueAnimator and the reverse repeat

I have a two line textview where I am attempting to do the following:
when data arrives, fade out the second line only
change the data presented in the second line
fade the second line back in
I am currently using the following code to accomplish this:
ValueAnimator alphaAnim = ValueAnimator.ofInt(255,0).setDuration(1000);
alphaAnim.setRepeatMode(ValueAnimator.REVERSE);
alphaAnim.setRepeatCount(1);
alphaAnim.setStartDelay(500);
alphaAnim.addUpdateListener(valueAnimator -> {
int alpha = (int) valueAnimator.getAnimatedValue();
int newColor = binding.ForegroundSpanText.getCurrentTextColor() & 0x00ffff | (alpha <<24);
SpannableString tempStringHolder = binding.getAnimString();
if(fadingSpan !=null){
tempStringHolder.removeSpan(fadingSpan);
}
fadingSpan = new ForegroundColorSpan(newColor);
tempStringHolder.setSpan(fadingSpan, tempStringHolder.toString().indexOf("\n"), tempStringHolder.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
if(Integer.toHexString(newColor).equals("1000000") && !tempStringHolder.toString().equals("This is my test text with lots of text\n and this is the new text that will animate in!!")){
animStringHolder = new SpannableString("This is my test text with lots of text\n and this is the new text that will animate in!!");
binding.setAnimString(animStringHolder);
binding.executePendingBindings();
}else{
binding.setAnimString(tempStringHolder);
}
});
The issues I am currently running into are:
The change between the initial text and the text I change to is still visible because the reverse animation happens immediately, so I am looking for a way to add a delay between the reversal. I realize that this could be done with a second animator but was hoping someone might have some idea of how to accomplish this without.
Also if anyone has a better way to set the data/check if the end point of the first animator has been reached that would be awesome, I tried to override the onAnimationEnd() function but that occurs when the entire animation finishes, meaning after the reverse repeat.
In further research I found onAnimationRepeat() which is part of AnimationListenerAdapter. So the code to make this a part of what I posted originally would look like:
alphaAnim.addListener(new AnimatorListenerAdapter(){
#Override
public void onAnimationEnd(Animator animation){
System.out.println("Finished");
}
#Override
public void onAnimationRepeat(Animator animation){
animStringHolder = new SpannableString("This is my test text with lots of text\n and this is the new text that will animate in!!");
binding.setAnimString(animStringHolder);
}
});

getText() always return empty string from dynamically created Chip component?

I'm trying to dynamically create some choice chip components based on an ArrayList of String from some computation and following are the code to create the chips and adding them to a ChipGroup created in layout XML file.
if (mChipGroup.getChildCount() == 0 ){
int i = 0;
for (Classifier.Recognition res: results){
Chip resultChip = new Chip(getDialog().getContext());
ChipDrawable chipDrawable =
ChipDrawable.createFromAttributes(
getActivity(),
null,
0,
R.style.Widget_MaterialComponents_Chip_Choice);
resultChip.setId(i++);
resultChip.setChipDrawable(chipDrawable);
resultChip.setText(res.getTitle());
mChipGroup.addView(resultChip);
}
}
The Chips displayed correctly with the text but when I tried to call getText() on the chips, it always return empty String but not the text contained by the chips. I tested this by setting the OnCheckedChangeListener on the ChipGroup and making a Toast with the text (though it didn;'t work). When I tried to display only the checkedId it works.
mChipGroup.setOnCheckedChangeListener(new ChipGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(ChipGroup group, int checkedId) {
Chip chip = group.findViewById(checkedId);
if(chip != null){
Toast.makeText(getContext(), chip.getText().toString(),Toast.LENGTH_SHORT).show();
}
}
});
My current workaround is to have a variable holding the array results and use ArrayList.get(selectedChipId.getTitle()). but don't think it should be that way though
I also found that it is able to get text from Chips added in layout file but not run-time added Chips. Tried with both 1.1.0/alpha06 and 1.1.0/alpha07 release but am having no luck. Would like to have some advice if possible. Thank you very much.
So, it seems like a bug as per answered in here and here. Current workaround is to use ((ChipDrawable) chip.getChipDrawable()).getText() instead.

Android : Add text to create a list with image at the top.

I am working on an Android application in which I am working on letting the user add some text below the image, and then the text will be saved in the database on server. The user must be able to add text as shown in the screenshot below. Please note that the user can decide that the text entered can go below the screen as well.
Mock image(Apologies for my horrible Gimp skills... :D )
Now as you can see on the top, there will be a header image with which the the display will start with. Then below that I would like to put additional EditText fields ideally, but the problem is that the user can go on entering the text, and the EditText field might get over. This is the first problem I am tackling. The only way I could think of is to add an EditText via code in a loop or after a scroll, etc. Any other solutions for the same.
The 2nd problem is I will save all the text information on our server, but how will I properly align that information as it was entered by the first user and display them for the 2nd user.
Kindly let me know if there are any better solutions for the first problem and a strategy for the 2nd problem. Thank you.
For the first problem, you can do this - Add an ImageView and an EditText below it. Add a TextWatcher to the EditText to listen for user input. If the user enters some text, dynamically add another EditText below it. If the user clears the text, remove that EditText from the layout. Do the same for all EditTexts.
As for saving the text on your backend, you can number the text fields internally and save them on your server. When you retrieve this data, the numbers will indicate the order of the text.
mEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
// Add EditText to the list
} else {
// Remove the EditText from the list
}
}
});
You can base your further handling logic around this snippet. For example, remove the EditText when it is empty AND it loses focus...

Having problems updating the visibility of a button within a popup

I'm trying to get it so that when the user clicks popbtnnext within the popup, the program checks if the rest of the array flaggedwordsused is null. If not, the button is set to be visible and the program moves on. If it is null, the program updates the button to be invisible.
popbutnext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
f++;
for (int g= f+1; g<flagwordsused.length; g++) {
if (flagwordsused[g] != null) {
popbutnext.setVisibility(0);
break;
}
else{
poptv1.setText(""+f);
popbutnext.setVisibility(1);
}
}
}
});
flagwordsused is an array of 20 elements, f in my test case starts at 0 with the string "very" occupying element zero and all other values are null. I have a textView updating with values of f so that I know the program is getting to the else statement. That value is updating just fine but the visibility of the button never changes. Any help you could give me would be appreciated. The popuplayout was created in java, not xml if that makes any difference.
You should use the constants in View to set visibility instead. Makes the code easier to read too:
To make popbutnext invisible:
popbutnext.setVisibility(View.INVISIBLE);
To make popbutnext invisible and not take any space when building the layout:
popbutnext.setVisibility(View.GONE);
To make popbutnext visible:
popbutnext.setVisibility(View.VISIBLE);
The reason that it does not work for you is because the values are wrong. Invisible is 4, gone is 8, visible is 0. However, I still recommend to use the constants in the View class - you never know, they might change in coming Android versions. Take a look at this link, and the visibility parameter.

Change a value smoothly increasing in speed by holding down a button

I have been steaming over this one a few days now. I try to have a selector for a big range of numbers... within int-limits. You ought to hold down a button and the value should change slow and the longer you press the more rapid it changes. You all know that kind of button, don't you?! :D
It has to be precise, yet fast to enter the number. I use a OnTouchListener. The event allows to .getDownTime().
I tried a lot, but always only got it to skip numbers (not really but too fast to use) or not repeatingly increase the value while holding down the button. If run without changes it is pretty fast, but it would be nice, if it starts to make 10 100 or 1000-jumps if it is held down long enough.
I prepared a little SSCCE looking like this:
public class ValueChangerSSCCE extends Activity implements OnTouchListener {
Button plusButton;
TextView valueView;
Button minusButton;
int value;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
plusButton = new Button(this);
plusButton.setText("+");
plusButton.setTextSize(120f);
plusButton.setOnTouchListener(this);
layout.addView(plusButton);
valueView = new TextView(this);
valueView.setGravity(Gravity.CENTER_HORIZONTAL);
valueView.setTextColor(Color.WHITE);
valueView.setText(value + "");
valueView.setTextSize(120f);
layout.addView(valueView);
minusButton = new Button(this);
minusButton.setText("-");
minusButton.setTextSize(120f);
minusButton.setOnTouchListener(this);
layout.addView(minusButton);
setContentView(layout);
}
/*
* Called when a button is pressed
*/
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v == plusButton) {
value++;
} else if (v == minusButton) {
value--;
}
valueView.setText(value + "");
return false;
}
}
For devices with low resolution one might have to decrease the text-sizes.
Thanks in advance!
Have a look at the NumberPicker source code. This is a widget from the SDK that does exactly what you are describing, except without the acceleration. Using post calls to a Handler as is done here is the best way to handle the timing events. The only addition you would need to make to this class is to vary the mSpeed value in the post callbacks (and perhaps the increment) based on the down time.
HTH.
The way I might try and tackle this is as follows:
Pressing + or - will start a Thread. The thread updates the number at a set interval by an offset value, if the number has changed more than 20 times then decrease the interval so the number updates faster, if the number is still changing a lot then the offset value would be made larger to skip numbers. Remember all this is happening in a thread.
When the user lifts their finger the thread is killed and the offset, interval is reset.
Use the value of getDownTime() to compute how big the counter increment should be.
First, design the response curve you would like. (That is, determine a function that defines how the value should change as a function of touch time and, perhaps, starting value. It does not — should not, from the way you describe it — be a straight line function.)
Then just make your increment follow the curve. It will probably help to store the button value and down time at the last event.

Categories