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

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.

Related

CountDownTimer doesn't count down by the specified intervals

I'm trying to build a count-down timer function in my app, however, it doesn't run as expected.
timer = new CountDownTimer(100, 10) {
#Override
public void onTick(long l) {
Log.d(TAG, "onTick: " + l);
}
#Override
public void onFinish() {
}
}.start();
My expectations are that it would count down gradually from 100,90,80...till 0
Although the output timer is showing quite random times (34 then 18 then 8..etc).
How can I achieve what I want?
It's difficult to explain the exact idea I'm trying to achieve but basically, I'm using touch listeners to hover over an item which in turn loads a few other items in the view. For some reason, there should be an intentional delay of around 100ms before these items could be displayed. I'm trying to build a progress bar that tells the user that something is loading rather than giving the impression that the screen is just stuck. I hope that helps to give a better idea of what I'm trying to achieve

Changing image in adjacent ImageButtons (Android)

So I'm trying to make a little game for Android. It's about turning lights on and off. I have 25 ImageButtons and, when I press one, I need the ones that are adjacent (up, left, down, right) to change too.
The thing is that I can't find a way to get/identify this buttons.
I tried using "view.getX()" and "view.getY()" but don't know how to implement them the right way (if there is one).
Here's the code I use to change ONE button:
public void change(View view)
{
String state = view.getTag().toString();
if (state.equals("on"))
{
view.setBackgroundDrawable(getResources().getDrawable(R.drawable.lightOff));
view.setTag("off");
lightsOn -= 1;
txtNumLights.setText(String.valueOf(lightsOn));
}
if (state.equals("off")) {
view.setBackgroundDrawable(getResources().getDrawable(R.drawable.lightOn));
view.setTag("on");
lightsOn += 1;
txtNumLights.setText(String.valueOf(lightsOn));
}
}
I use the tags to know if it's On or Off and set a txtView with the number of ON lights.
But, to the point, how do I get the ones adjacent to this one?
Thanks in advance.
You have to store the buttons on a bidimensional array.
When you click on one button, you set the tag and the background on the buttons you are interested on.
Pseudocode:
If (button_matrix[row][column] is clicked) then
Set_tag_background (button_matrix[row-1][column])
Set_tag_background (button_matrix[row+1][column])
Set_tag_background (button_matrix[row][column-1])
Set_tag_background (button_matrix[row][column+1])
Set_tag_background (button_matrix[row][column])
...
On the implementation you should take care about not generating ArrayOutOfBoundsException...

LWJGL: detecting left/right clicks when getButtonCount returns 0

On the Dell Inspiron 15 3000, the touchpad doesn't have any physical left/right buttons. Instead, it is one giant touchpad that is pressure sensitive. I'm assuming it detects right/left clicks based off of hand position on the trackpad.
In my LWJGL application, I detect mouse button clicks with Mouse.isButtonDown(0). This works fine on computers with a mouse with physical buttons, but doesn't work on touchpads that lack physical buttons. Mouse.getButtonCount() returns 0.
Has anybody had any success in detecting if a mouse button is pressed, should the user be using a trackpad that doesn't have physical buttons?
I think, instead of using
org.lwjgl.input.Mouse
This class could be what you are searching for:
org.lwjgl.input.Controllers
http://legacy.lwjgl.org/javadoc/org/lwjgl/input/Controllers.html
Im not entirely sure though since I only have a mouse and no way to test this with a touchpad.
For those who find this in the future, I did find a fix:
You cannot, should there be no physical buttons, use the Mouse.isButtonDown() method. Instead, you are going to have to read the event buffer. To do so, I wrote my own helper class:
public class Mouse{
private static boolean button_left = false, button_right = false;
public static boolean isButtonDown(int button){
if(button == 0) return button_left;
if(button == 1) return button_right;
return false;
}
public static void update(){
while(org.lwjgl.input.Mouse.next()){
if(org.lwjgl.input.Mouse.getEventButton() == 0) button_left = org.lwjgl.input.Mouse.getEventButtonState();
if(org.lwjgl.input.Mouse.getEventButton() == 1) button_right = org.lwjgl.input.Mouse.getEventButtonState();
}
}
}
The update() method is called every tick, and as such I can get button states using Mouse.isButtonDown(button).

Loop Not performing as expected when using detachChild() and addChild()

This question refers to andengine GL-ES1.
I am having trouble making a wallpaper activity that refreshes when your return to it, or when the user performs actions in the game.
My game has two activities. In one, you can edit and arrange the background elements in a room. In the other you play the game, and it uses the same background with the elements you arranged in the first activity.
There is also a live wallpaper in which your room is the background and characters move around in front of it.
I am making updtaes in onResume() in the wallpaper.
first I detach all the backgroudn sprites i used before.
Then I attach new sprites in the updated positions.
What happens is: some of the sprites don't show up.
Here is the method: Can you see anything I'm doing wrong?
private void loadBackgroundDecorations() {
//Add new decorations
Log.d(TAG, "loadBackgoundDecorations");
mEngine.runOnUpdateThread(new Runnable() {
#Override
public void run() {
// Remove Old Decorations
Log.d(TAG, "loadBackgoundDecorations: decorationList.size() =" + decorationList.size());
while(decorationList.size() > 0){
Sprite d = decorationList.remove(0);
scene.detachChild(d);
Log.d(TAG, "loadBackgoundDecorations: detachChild");
}
decorationList.clear();
//Add new decorations
ArrayList<Integer> decorations = app.getBackgroundManager().getDecorations();
Log.d(TAG, "loadBackgoundDecorations: decorations.size()" +decorations.size());
for (int i = 0; i < decorations.size(); i+=3) {
Log.d(TAG, "Decoration Values: texture-"+decorations.get(i)+", x-"+decorations.get(1+i)+", y-"+decorations.get(2+i));
Sprite draggable = new Sprite(decorations.get(1+i),decorations.get(2+i),mGameTextureRegionLibrary.get(decorations.get(i)));
draggable.setIgnoreUpdate(true);
scene.attachChild(draggable,0);
decorationList.add(draggable);
Log.d(TAG, "loadBackgoundDecorations: attachChild"+ i);
}
}
});
}
#Override protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
BitmapTextureAtlasTextureRegionFactory.createFromAsset(mTexture, this, app.getAquariumBackground(), 0, 0);
addBubbles();
loadBackgroundDecorations();
addCharacters()
}
============ UPDATE =================
As some people have suggested below, I tried adding all the scene setup functions into the runnable. This has no effect. What has worked for me is to set the "wrong" decorations visible property to "false". But I am worried that this will eventually cause a memory leak as more and more duplicates of the sprites are hidden on the wallpaper.
The problem only exists when I call "detachChild". For some reason that seems to prevent "attachChild" from firing correcly. Anybody have ideas for what could be causing this?
Can anyone else create an activity that adds and removes sprites in the onResume function?
I am fairly certain that the error has to do with your onResume method. The order you have your methods in is
addBubbles();
loadBackgroundDecorations();
addCharacters()
but your loadBackgroundDecorations uses a runnable so there is no guarantee that the method will run in between.
My Explanation:
From what I understand both addCharacter and addBubbles will be running on the UIthread whereas the loadBackgroundDecorations method will run on the update thread. The two threads will go through the methods at different times and that is where you are seeing some inconsistencies.
To Fix:
Put addBubbles and addCharacters in the same runnable in the order that you want and it should work as expected.

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.

Categories