I'm working on a music player for android.
In it I have an activity which contains ListView that displays songs/artists/albums etc.
I keep track of the lists the user views (For example all album --> artist x --> album y)
In order to provide a way for the user to go back in the lists, I override onBackPressed() so it will pick the previous list the user viewed (handled by a Stack)
#Override
public void onBackPressed()
{
if (ListActivity.onScreenList == ListActivity.ALL_SONGS && viewStack.empty())
super.onBackPressed();
else if (viewStack.empty())
navListView.performItemClick(navListView.getChildAt(0), 0, navListView.getChildAt(0).getId());
else
{
TypeAndName tan = viewStack.pop();
if (tan.getName() == null)
{
int num = tan.getType();
navListView.performItemClick(navListView.getChildAt(num), num, navListView.getChildAt(num).getId());
}
else
{
switch (tan.getType())
{
case ARTISTS:
break;
case ALBUMS:
{
Album alb = albumListAdapter.getAlbumAtPosition(position);
c = db.rawQuery(DatabaseHandler.qryGetSongsByAlbum, new String[] { alb.getAlbumName() });
songListAdapter.setPlaylist(DatabaseHandler.convertCursorToSongsArray(c));
lv.setAdapter(songListAdapter);
ListActivity.onScreenList = ListActivity.ALL_SONGS;
}
break;
case GENRES:
break;
case PLAYLISTS:
break;
case YEAR:
break;
// TODO add other options here
}
}
}
}
the weird part is, that the back sound (the one that is played whenever you press the back button) is played twice.
However, the onBackPressed() method is not called twice and the code works as expected.
Related
I want to navigate Angular single page application without reloading the webpage. On button click I'm calling following code to navigate.
String fullUrl = "https://example.com/page1";
String hashUrl = "/page1";
public void goBackInWebView(String fullUrl, String hashUrl) {
WebBackForwardList history = webview.copyBackForwardList();
int index;
int currentIndex = history.getCurrentIndex();
for (int i = 0; i < history.getSize(); i++) {
index = i - currentIndex;
if ((webview.canGoBackOrForward(1 + i)) || (webview.canGoBackOrForward(1 - i))) {
if (history.getItemAtIndex(i).getUrl().endsWith(hashUrl)) {
webview.goBackOrForward(index);
break;
} else if (i == history.getSize()) {
webview.loadUrl(fullUrl);
break;
}
} else {
//OUTER ELSE
webview.loadUrl(fullUrl);
break;
}
}
}
If the webpage is not saved in the history it will call webview.loadUrl(fullUrl); else it will load the page using webview.goBackOrForward(index);.
but is above code everytime OUTER ELSE is callling.
First of all canGoBackOrForward is used for Getting whether the page can go back or forward the given number of steps. as you mentioned in question your web page is single page so you don't need call this method. I think bellow code can solve your problem.
public void goBackInWebView(String fullUrl, String hashUrl) {
WebBackForwardList history = webview.copyBackForwardList();
if (history.getSize() == 0) {
webview.loadUrl(fullUrl);
}else {
for (int i = 0; i < history.getSize(); i++) {
if (history.getItemAtIndex(i).getUrl().endsWith(hashUrl)) {
webview.goBackOrForward(i);
break;
} else {
webview.loadUrl(fullUrl);
}
}
}
}
I find it difficult to see much relation to Android and WebView, because the problem is SPA.
Better use hashtag # navigation for SPA, because this won't request anything server-side.
The point simply is, that the back button does not matter the least, while never navigating.
One just needs to bind JavaScript, which runs whenever window.location.hash changes.
I am trying to convert my PC game code in unity to android and I am stuck on the controls change. Please help!
This is the code:
Getting the state of rocket.
enum State { Dying, Alive, Transcending }
State state = State.Alive;
// Update is called once per frame
void Update()
{
if (state == State.Alive)
{
RespondToThrustInput();
RespondToRotateInput();
}
}
When the rocket collides with anything it checks whether it's friendly or not before changing its state from alive to dead.
private void OnCollisionEnter(Collision collision)
{
if (state != State.Alive) { return; }
switch (collision.gameObject.tag)
{
case "Friendly":
break;
case "Finish":
state = State.Transcending;
audioSource.Stop();
audioSource.PlayOneShot(finishgame);
finishgameParticles.Play();
Invoke("LoadNextScene", levelloaddelay);
break;
default:
state = State.Dying;
audioSource.Stop();
audioSource.PlayOneShot(death);
deathParticles.Play();
Invoke("LoadFirstScene", levelloaddelay);
break;
}
}
private void LoadFirstScene()
{
SceneManager.LoadScene(9);
}
Loading next scene using build index.
private void LoadNextScene()
{
if (nextscenetoload > 7)
{
nextscenetoload = 0;
}
SceneManager.LoadScene(nextscenetoload);
}
Space for ignition or force and audio sources for playing sound effects.
private void RespondToThrustInput()
{
if (Input.GetKey(KeyCode.Space))
{
ApplyThrust();
}
else
{
audioSource.Stop();
mainengineParticles.Stop();
}
}
Apply thrust is the method I wrote with the logic of the rocket thrust.
private void ApplyThrust()
{
rigidbody.AddRelativeForce(Vector3.up * mainThrust * Time.deltaTime);
if (!audioSource.isPlaying)
audioSource.PlayOneShot(mainengine);
mainengineParticles.Play();
}
Rotation of the rocket or Left and right. Here I am trying to rotate the rocket using the A and D keys
void RespondToRotateInput()
{
float rotationThisFrame = rcsThrust * Time.deltaTime;
if (Input.GetKey(KeyCode.A))
{
rigidbody.freezeRotation = true;
transform.Rotate(Vector3.forward * rotationThisFrame);
rigidbody.freezeRotation = false;
}
else if (Input.GetKey(KeyCode.D))
{
rigidbody.freezeRotation = true;
transform.Rotate(-Vector3.forward * rotationThisFrame);
rigidbody.freezeRotation = false;
}
}
For PC games there is a keyboard to use to control, but for the android there are touches, you have to verify if there is a touch on the screen, like this:
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
//do something
}
also you need more work to determine where the touch is located and do you customizations... or in case you're not interested about this input handling, you can use some assets from Unity Assets Store to cover this part for you.
check this link for more information about touch control in Unity documentation:
https://docs.unity3d.com/ScriptReference/Input.GetTouch.html
I'm planning to make a digital magazine with adobe flash cc 2014. I have different scenes for different page and I use Gesture_SWIPE to navigate the magazine.
The problem is, I only write the script in 1 scene but it worked for all the scenes. So I can do the swipe in all scenes.
While I want each scenes have a different action such as only page 1 that can't be swiped to the left, only page 2 can be swiped up and down and etc
I did use the if else in each case, it worked for the swiped left, but not working for the swipe right.
Can you please help me? How can I make this scripts work only for 1 scene?
This is my gesture swipe code:
import flash.events.TransformGestureEvent;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, SwipeHandler);
function SwipeHandler(event:TransformGestureEvent):void
{
switch(event.offsetX)
{
case 1: //swiped right
{
prevScene();
break;
if(this.currentScene.name == "Scene 1") //THIS ONE DIDN'T WORK
{
stop();
}
}
case -1: //swiped left
{
if(this.currentScene.name == "Scene 12") //THIS ONE WORK
{
stop();
}
else
{
nextScene();
break;
}
}
}
}
I had a little trouble understanding your problem and requirements but a few things to continue with:
your first case should probably work in the same way as the 2nd
your breaks won't be always fired so will sometimes flow onto the next case the way your statement were setup.
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, SwipeHandler);
function SwipeHandler(event:TransformGestureEvent):void {
switch(event.offsetX) {
case 1:
if(this.currentScene.name == "Scene 1") {
stop();
} else {
prevScene();
}
break;
case -1:
if(this.currentScene.name == "Scene 12") {
stop();
} else{
nextScene();
}
break;
default:
//something else happened
}
}
I have a menu Activity with several options. One of them is to post to a news feed using Glass's speech-to-text. I looked at https://developers.google.com/glass/develop/gdk/input/voice#starting_the_speech_recognition_activity
and have it all implemented, but the onActivityResult method apparently never gets called.
On the Glass device, I'm able to select "New Post" in the menu and the voice capture comes up. I can speak to it and it'll convert my speech to text on the screen. But after I accept it (by tapping or waiting a few seconds), it just exits and takes me back to the home screen. I need to be able to get the speech text String in onActivityResult and call another method (displayPostMenu) to show another menu to process the text but I can't do that if onActivityResult is never called.
I've looked at several similar issues but none of the solutions have worked/were applicable... I don't think I can setResult() on RecognizerIntent.ACTION_RECOGNIZE_SPEECH since it's Google's? Any help would be greatly appreciated!
Some pieces of my code:
private final int SPEECH_REQUEST = 1;
//Code to make this Activity work and the menu open...
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.view_feed:
//Stuff
return true;
case R.id.new_post:
Log.i("MainMenu", "Selected new_post");
displaySpeechRecognizer();
Log.i("MainMenu", "Ran displaySpeechRecog under new_post selection");
return true;
case R.id.stop:
Activity parent = getParent();
Log.i("MainMenu", "Closing activity; parent: " + parent + "; " + hashCode());
if (parent != null && parent.getApplication() == getApplication()) {
finish();
} else {
MainMenu.close();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onOptionsMenuClosed(Menu menu) {
// Nothing else to do, closing the Activity.
finish();
}
public void displaySpeechRecognizer() {
Log.i("MainMenu", "Entered displaySpeechRecognizer");
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
startActivityForResult(speechIntent, SPEECH_REQUEST);
Log.i("MainMenu", "Finished displaySpeechRecognizer. startActivityForResult called.");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i("MainMenu", "onActivityResult entered from MainMenu");
switch (requestCode) {
case SPEECH_REQUEST:
Log.i("MainMenu", "onActivityResult enters SPEECH_REQUEST case");
if (resultCode == RESULT_OK) {
Log.i("MainMenu", "onActivityResult enters RESULT_OK for voice cap");
List<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String spokenText = results.get(0);
Log.i("MainMenu", "SpokenText:" + spokenText);
holdText = spokenText;
if (holdText != "") {
displayPostMenu();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
You say this is a "menu activity", so does that mean that it's attached to a live card?
If so, are you overriding onOptionsMenuClosed and calling finish inside it?
If you are, the menu activity will finish and destroy itself before the speech activity returns, so there will be no place for the result to go back to.
One approach to fix this would be to use a flag to indicate whether you should defer the call to finish when the menu is closed, and make that call conditionally inside onOptionsMenuClosed based on that flag. Then, set that flag in your displaySpeechRecognizer method and wait until the end of your onActivityResult processing to call finish instead.
Something like this should work (written without testing, may contain typos):
private boolean shouldFinishOnMenuClose;
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// By default, finish the activity when the menu is closed.
shouldFinishOnMenuClose = true;
// ... the rest of your code
}
private void displaySpeechRecognizer() {
// Clear the flag so that the activity isn't finished when the menu is
// closed because it will close when the speech recognizer appears and
// there won't be an activity to send the result back to.
shouldFinishOnMenuClose = false;
// ... the rest of your code
}
#Override
public void onOptionsMenuClosed(Menu menu) {
super.onOptionsMenuClosed();
if (shouldFinishOnMenuClose) {
finish();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SPEECH_REQUEST) {
if (resultCode == RESULT_OK) {
// process the speech
}
// *Now* it's safe to finish the activity. Note that we do this
// whether the resultCode is OK or something else (so the menu
// activity goes away even if the user swipes down to cancel
// the speech recognizer).
finish();
}
}
I am trying to make a donation menu for my app. I have figured out the part that when a user clicks donate, more buttons come up saying how much. Now, I want to be able to have the amount buttons go away if they click the same button again. I want the regular DonateButton to remain. How would I come about doing that?
I have already set it as invisible using purchaseButton.setVisibility(View.GONE);
Here is the code for clicking the button and the other buttons appearing:
public void onClick(View v) {
switch (v.getId()) {
case R.id.DonateButton:
purchaseButton.setVisibility(View.VISIBLE);
purchaseButton2.setVisibility(View.VISIBLE);
purchaseButton3.setVisibility(View.VISIBLE);
case R.id.Donate:
if(BillingHelper.isBillingSupported()){
BillingHelper.requestPurchase(mContext, "donate");
// android.test.purchased or android.test.canceled or android.test.refunded
} else {
Log.i(TAG,"Can't purchase on this device");
}
break;
default:
// nada
Log.i(TAG,"default. ID: "+v.getId());
break;
case R.id.Donatetwo:
if(BillingHelper.isBillingSupported()){
BillingHelper.requestPurchase(mContext, "donate2");
// android.test.purchased or android.test.canceled or android.test.refunded
} else {
Log.i(TAG,"Can't purchase on this device");
}
break;
case R.id.Donatethree:
if(BillingHelper.isBillingSupported()){
BillingHelper.requestPurchase(mContext, "donate3");
// android.test.purchased or android.test.canceled or android.test.refunded
} else {
Log.i(TAG,"Can't purchase on this device");
}
break;
}
}
Screenshot of what I mean:
IMAGE URL (DON'T HAVE 10 REPUTATION YET):
http://i.stack.imgur.com/AMdhS.png
What I am trying to say is.
The app comes up just showing the "Donate!" Button. =>
The user clicks the "Donate!" Button. =>
The buttons "Donate $1", "Donate $3", and "Donate $5" appear. =>
I NEED HELP FROM HERE
A user wants to close the "Donate $1", "Donate $3", and "Donate $5" Buttons. =>
To close them, they click the "Donate!" which was the button they used to open it all. =>
The "Donate $1", "Donate $3", and "Donate $5" go away.
I want it to still allow them to open and close those buttons more than once though.
a simple state variable should do.
put this in your field definition area:
boolean areButtonAmountVisible = false;
and this code as your onClick():
case R.id.DonateButton:
if( areButtonAmountVisible )
{
areButtonAmountVisible = false;
purchaseButton.setVisibility(View.GONE);
purchaseButton2.setVisibility(View.GONE);
purchaseButton3.setVisibility(View.FONE);
}
else
{
areButtonAmountVisible = true;
purchaseButton.setVisibility(View.VISIBLE);
purchaseButton2.setVisibility(View.VISIBLE);
purchaseButton3.setVisibility(View.VISIBLE);
}
Try this.
Use getVisibility() method to know the visible state of button.
int visibility;
visibility = button.getVisibility();
if(visibility == View.VISIBLE) {
button.setVisibility(View.INVISIBLE);
} else {
button.setVisibility(View.VISIBLE);
}
You have to check like this for every button.
I will suggest one more thing.
Take a global variable and use it as notifier, use below code in all button click functions.
boolean again = false;
if (again) {
// make all invisible
again = false;
} else {
// make all visible
again = true;
}