After finding that starting a new intent might not be the right way to notify user of GameOver, I'm now struggeling with runOnUiThread, Runnable and dialogs..
Question : How and where would I implement a Dialog.show() to notify the user that the game has ended? I am implementating a Rail race Game .In this when trains collision occur game over i want to show dialog here.
I've experimented with runOnUiThread, Runnable and Async threads. Can't figure it out.
I want to show dialog in collision occur method of MainGamePanel.
I have a game. Activity AndroidGameActivity :
private static final String TAG = AndroidGame.class.getSimpleName();
public static Vibrator v;
private GameDatabaseOperations gameDatabaseOperations;
private int currentDate;
private int todayDate;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
try{
currentDate = Calendar.getInstance().get(Calendar.DATE);
gameDatabaseOperations = new GameDatabaseOperations(this);
gameDatabaseOperations.createWriteModeDatabase();
Cursor crDate = gameDatabaseOperations.fetchTodayDate();
startManagingCursor(crDate);
if(crDate!= null && crDate.getCount() >0){
crDate.moveToFirst();
todayDate = crDate.getInt(0);
}
if(currentDate != todayDate ){
gameDatabaseOperations.updateTodayDefaultScore(0);
gameDatabaseOperations.updateTodayDate(currentDate);
Cursor cr1Date = gameDatabaseOperations.fetchTodayDate();
startManagingCursor(cr1Date);
if(cr1Date!= null && cr1Date.getCount() >0){
cr1Date.moveToFirst();
todayDate = cr1Date.getInt(0);
}
}
gameDatabaseOperations.closeDatabase();
}
catch(Exception e){
e.printStackTrace();
}
FrameLayout fl = new FrameLayout(this);
setContentView(fl);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout pause = (LinearLayout) inflater.inflate(
R.layout.pausebutton, null);
fl.addView(new MainGamePanel(this));
fl.addView(pause);
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
}
have you thought of implementing your game's engine like this:
while (!collision)
{
playGame();
doAnimation();
checkCollision();
}
dialog.show();
performAction(determineNextGameState());
putting all the game play code in the playGame() and then modifying collision field when the user dies?
Related
I want to access the object of Dialog in MainActivity.
For example, in the MainActivity, use the Button to pop up a dialog.
case R.id.txtCalibMain:
SubMenu_Calib mCalibDialog = new SubMenu_Calib(instance);
mCalibDialog.show();
break;
In this way, but in the previous steps, before the Dialog
If you want to preserve the text content of the TextView inside the Dialog
How can you approach it?
Currently, Dialog is defined and called by using a separate class.
I'm trying to access it from the outside, so I'm importing a null value or an undefined TextView.
It is natural that an error will be raised.
Dialog Activity Code
public class SubMenu_Units extends Dialog implements View.OnClickListener {
public static SubMenu_Units mSubMenu_Units;
public static MainActivity instance;
public static List<SingleItem> singleItems;
static SingleAdapter mSingleAdapter;
public static TextView mtxtTestMenu;
public SubMenu_Units(Context context) {
super(context);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.submenu_units_layout);
mSubMenu_Units = this;
initialize();
mtxtTestMenu = (TextView)findViewById(R.id.txtTestCenterMenu);
}
void initialize()
{
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
setCanceledOnTouchOutside(true);
ColorDrawable dialogColor = new ColorDrawable(0xFF424957); // 0xFF424957
getWindow().setBackgroundDrawable(dialogColor);
mOrientation = getContext().getResources().getConfiguration().orientation;
WindowManager.LayoutParams mPortrait_params = getWindow().getAttributes();
mPortrait_params.width = 375;
mPortrait_params.height = 945;
mPortrait_params.gravity = Gravity.CENTER | Gravity.LEFT;
mPortrait_params.x = 5;
mPortrait_params.y = 68;
getWindow().setAttributes(mPortrait_params);
}
You need to have common class where you need to copy below code
i.e; You need to extend below CurrentActivity with CommonActivity
//In Current Activity
case R.id.txtCalibMain:
exitAlert("Some Message)
break;
// Main Acitivty
public void exitAlert(final String message) {
LayoutInflater inflater = LayoutInflater.from(this);
View mExitAlertView = inflater.inflate(R.layout.alert_exit_logout_dialog, null);
final Dialog dialog = new Dialog(this, android.R.style.Theme_Translucent);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(mExitAlertView);
dialog.setCanceledOnTouchOutside(true);
TextView txtAlertMessage = (TextView) mExitAlertView.findViewById(R.id.txtAlertMessage);
txtAlertMessage.setText(message);
mExitAlertView.setOnTouchListener((v, event) -> {
dialog.dismiss();
return false;
});
Button btnExitAlertNo = (Button) mExitAlertView.findViewById(R.id.btnExitAlertNo);
btnExitAlertNo.setOnClickListener(v -> dialog.dismiss());
Button btnExitAlertYes = (Button) mExitAlertView.findViewById(R.id.btnExitAlertYes);
btnExitAlertYes.setOnClickListener(v -> {
dialog.dismiss();
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
});
dialog.show();
}
I'm displaying an animated gif in an ImageView, and a transparent background TextView on top of that. I want to be able to dynamically change the text in the TextView based on the current frame being displayed in the animation. Is there a mechanism to do this?
I found an answer. I implemented Drawable.ICallback and then use AnimationDrawable.GetFrame() to set the callback on each frame I need.
private class MyFragment : DialogFragment, Drawable.ICallback
{
TextView tv; /* this is later defined in OnCreateDialog */
...
/* Must implement */
public void InvalidateDrawable(Drawable who)
{
/* As you can see in OnCreateDialog(), this gets called for
frames 0 and 56 */
if (iVocabIndex == 0) {
tv.Text = "Show this text";
iVocabIndex = 1;
}
else if (iVocabIndex == 1) {
tv.Text = "Show this other text";
iVocabIndex = 0;
}
}
/* Must implement */
public void ScheduleDrawable (Drawable who, IRunnable what, long when)
{
}
/* Must implement */
public void UnscheduleDrawable (Drawable who, IRunnable what)
{
}
public override Dialog OnCreateDialog (Bundle savedInstanceState)
{
ImageView image = view.FindViewById<ImageView> (Resource.Id.confDialogImage);
tv = view.FindViewById<TextView> (Resource.Id.confDialogImageText);
image.SetImageResource (Resource.Drawable.my_animation_xml);
AnimationDrawable b1Anim = (AnimationDrawable)image.Drawable;
b1Anim.Start();
Drawable d = b1Anim.GetFrame(0);
d.Callback = this;
d = b1Anim.GetFrame(56);
d.Callback = this;
}
I have to build a custom dialog that update the view when the content view is changed.
In the example below I have two TextView, one in the main activity and one in the dialog layout and counter from 1 to 10 should showed on both (main activity layout and dialog layout), but only the TextView in the main activity is update.
The code:
TextView tvCounter_Dialog, tvCounter_OutsideDialog;
int counter = 0;
Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_custom_dialog);
handler = new Handler();
View dialogView = getLayoutInflater().inflate(R.layout.dialog_live_layout, null);
tvCounter_Dialog = (TextView) dialogView.findViewById(R.id.tvCounter);
tvCounter_OutsideDialog = (TextView) findViewById(R.id.tvCounter_outsideDialog);
Dialog counterDialog = new Dialog(this);
counterDialog.setContentView(R.layout.dialog_live_layout);
counterDialog.show();
final Runnable updatedr = new Runnable() {
#Override
public void run() {
counter = (counter + 1) % 10;
tvCounter_Dialog.setText(String.valueOf(counter));
tvCounter_OutsideDialog.setText(String.valueOf(counter));
handler.postDelayed(this, 500);
}
};
updatedr.run();
}
So the question is - how can I update the textview in the dialog?
EDIT: here is an capture (to be more clear)
the mistake is on this line
counterDialog.setContentView(R.layout.dialog_live_layout);
it should be
counterDialog.setContentView(dialogView);
in your version the custom view of your Dialog and the one you inflated are different
I've got an activity where I can add bookmarks to a favourites list. Each favourite has got a button. When I click that button I have to go to that specific activity. But it shows me an error. The app doesn't crash, but the bookmarked activity isn't started from the click.
Here is the code for the "Favourites" activity:
public class FavouritesActivity extends Activity {
private TextView mEmptyText;
private LinearLayout mBookmarkLayout;
private Context mContext;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.favourites_layout);
mContext = this;
mEmptyText = (TextView) findViewById(R.id.empty_textview);
mBookmarkLayout = (LinearLayout) findViewById(R.id.bookmark_insert_point);
getAllKeys();
}
private void getAllKeys()
{
SharedPreferences sp = this.getSharedPreferences("favs", MODE_PRIVATE);
Map<String,?> keys = sp.getAll();
int count = 0;
for(Map.Entry<String,?> entry : keys.entrySet())
{
String value = entry.getValue().toString();
System.out.println("!!!!!!!!!!!!!!!!!value = "+value);
String delimiter = ",";
String[] values_array = value.split(delimiter);
addBookmark(values_array);
count++; //keep track of the number of bookmarks
}
//if there are no bookmarks, display a text view saying so. Otherwise, make the text view go away
if (count == 0)
{
mEmptyText.setVisibility(View.VISIBLE);
mEmptyText.setText(getString(R.string.no_favs));
}
else
mEmptyText.setVisibility(View.GONE);
}
private void addBookmark(String[] values_array)
{
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.fav_individual, null);
TextView text = (TextView) v.findViewById(R.id.bookmark_text);
text.setSelected(true);
ImageButton button = (ImageButton) v.findViewById(R.id.bookmark_button);
v.getContext();
text.setText(values_array[1]);
final String myClass = values_array[0];
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Class<?> cl = null;
try {
cl = Class.forName(myClass);
Intent myIntent = new Intent(mContext, cl);
startActivity(myIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
// insert into main view
mBookmarkLayout.addView(v, 0, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));
System.out.println("!!!!!!!!!!!!!!!!!!!!Just added a view");
}
}
The error is the onClick method, exactly in this line:
cl = Class.forName(myClass);
It gives me a ClassNotFoundException.
It seems that with this code I'm able to start an activity which is inside this package. But the problem is that the activity I want to start is inside a different package. The logcat says that it coulnd't find the activity in the current package.
So how can I open an activity from a different package in my case? Tha activity is declared in the manifest file.
Thank you.
Did you import the other package in your FavouritesActivity ?
Add this line at the top of your code and replace the words to match with your other package:
import com.yourotherpackage.name.yourclassname;
well i'm having some problem with android. Maybe its simple but i'm pretty new in android world (3, 4 days actually). Well i have an activity whitch runs an asyncTask that stands to reading data from a sensor network. The async Task only executes the function l.read() that by itself is a loop and keep allways "earing" the sensor network and when a new node joins to the sensor network, it tells the UI thread that one more node has joined, and so it has to update the view (witch has just one tab saying that no nodes exists and will now have to have one node available - besides this i even have to load an xml layout file for this tab ) the problem is that, when i preform the function that supostly creates a view and add a tab (that is properly working because when i call it on onCreate it works) the app do not respond anymore, however, Logcat gives me no errors. It look like it works but it is not showing anything.
Please, i dont expect you to read all this code, its just to hel to explain my problem. Its been 2 days and i'm still asking for a solution..
main Activity:
public class PrincipalActivity extends Activity implements OnClickListener
{
private Button Send;
private Button Options;
private TextView ERROR;
private Bundle extras;
private String IP;
private String PORT;
private TabHost tabs;
private ligação l;
View m_vForm;
TabHost tabHost;
CustomView Cview;
ReadsData read;
//constructor
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
CustomView vv = new CustomView(PrincipalActivity.this,0);
setContentView(vv);
//instanciating the objects
IP = new String();
PORT = new String();
extras = getIntent().getExtras();
IP = extras.getString("IP"); //get the IP and port from the previous activity
PORT = extras.getString("PORT");
ERROR = (TextView) findViewById(R.id.ERROR);
tabs = (TabHost) findViewById(R.id.tabhost);
tabs.setup();
Send = (Button) findViewById(R.id.SendCommand);
Send.setOnClickListener(this);
Options = (Button) findViewById(R.id.Options);
Options.setOnClickListener(this);
//=========================
CreateAView("No Nodes",false);
l = new ligação(IP, Integer.parseInt(PORT),this); //CLASS LIGAÇÃO
// RunnableThread rT1 = new RunnableThread("t1",l,this);
read = new ReadsData();
read.execute();
//Textviews (Values)
}
public void AddUpdateNodes(Nodes n,int func)
{
//func is 0 if it it to add a node or 1 if it is to update an existing one
if(func == 0)
{
String s = new String();
s+= n.GETSourceNodeID();
CreateAView(s, true);
Cview.addNewNode(n);
}
if(func == 1)
Cview.UpdateNodeInformation(n);
}
public void onClick(View v)
{
if(v == Send)
{
// if i call CreateAView here it works ok
ERROR.setText(IP);
}
if(v == Options)
{
ERROR.setText(PORT);
}
}
// CREATING A VIEW WITH THE TABS
public void CreateAView(String s,boolean nodesAvailable)
{
m_vForm = createTABForm(s,nodesAvailable);
setContentView(m_vForm);
}
private ViewGroup createTABForm(String s,boolean nodesAvailable1)
{
final boolean nodesAvailable = nodesAvailable1;
// construct the TAB Host
tabHost = new TabHost(this);
tabHost.setLayoutParams( new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT) );
// the tabhost needs a tabwidget, that is a container for the visible tabs
TabWidget tabWidget = new TabWidget(this);
tabWidget.setId(android.R.id.tabs);
tabWidget.setBackgroundColor(Color.BLUE);
tabHost.addView(tabWidget, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) );
// the tabhost needs a frame layout for the views associated with each visible tab
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.setId(android.R.id.tabcontent);
frameLayout.setPadding(0, 65, 0, 0);
tabHost.addView(frameLayout, new LinearLayout.LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) );
// setup must be called if you are not initialising the tabhost from XML
tabHost.setup();
// create the tabs
TabSpec ts = tabHost.newTabSpec("TAB_TAG_2");
ts.setIndicator(s); // creating a tabb with the specified name
ts.setContent(new TabHost.TabContentFactory(){
public View createTabContent(String tag)
{
// -- this tab contains a single control - the listview -- //
Cview = new CustomView(PrincipalActivity.this,nodesAvailable);
return Cview; // IS AN OBJECT FROM THE CLASS CustomView
}
});
tabHost.addTab(ts);
return tabHost;
}
////////////////////////////////////////////////////////////////
//Async Tasks
private class ReadsData extends AsyncTask
{
#Override
protected Object doInBackground(Object... params)
{
l.read();
return null;
}
protected void onPostExecute()
{
l.SocketClosed_();
}
}
}
//CLASS CUSTOM VIEW
public CustomView(Context context,boolean NodesAvailable)
{
super(context);
if(NodesAvailable) //loads a layout
{
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view=layoutInflater.inflate(R.layout.finallayout,this);
//only after inflate
ADC0 = (TextView) findViewById(R.id.ADC00);
}
else // loads another layout
{
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view=layoutInflater.inflate(R.layout.no_nodes,this);
}
}
public void addNewNode(Nodes n)
{
String s = new String();
s = new String();
s += n.GETSensores(0).GETvalor();
ADC0.setText(s);
}
public void UpdateNodeInformation(Nodes n)
{
String s = new String();
s += n.GETSourceNodeID();
//if(s.equals())
}
}
//SOME CODE OF LIGAÇÃO CLASS
public class ligação
{
protected PrincipalActivity cont;
//Constructors
public ligação(String ss,int Port,PrincipalActivity c){ s=ss; p=Port;cont = c; }
public void read()
{
while(flag)
{
...
cont.AddUpdateNodes(node, 0);
...
}
Many thanks in advance
it's weird that your app doesn't crash , since all UI operations should be done on the UI thread . maybe it's because the asynctask's thread has crashed but not the ui thread , and that's why nothing occurs.
anyway , in order to create/update the view within the asyncTask , you can use any of the following , which will post something to the UI thread to do as soon as it can :
use a handler.
use publishProgress.
use runOnUiThread.