Hello Android developers,
i'm facing a strange behaviour of some views after activity restart - there are some views, which are not "visible", but they are layouted and react on Touch actions.
I'm trying to keep the application follow Android lifetime guide. I drop the Activity to background and let system to close my activity. Then I navigate back to my activity, which is recreated. There is no problem with data to be corrupted (saved in db with every change made), but the views are. There are some properly shown, but everything inside TableView, which is inside ScrollView, is not visible. If I call getVisibility() on any of not shown views, i get that it is visible. As I mentioned above, views are not "visible", but react on Touch and scroll events, like they were properly shown.
This is also hard (impossible) to debug, cause when the app is closed, debbuger is disconnected. But anyway, recreation follows the same methods callback - onCreate(), onStart(), onResume(), so once created, why there's problem other time? The only difference to me is that there is a null Bundle in onCreate(Bundle) when Activity is newly created and not null when it is recreated by system. If the activity is only stopped (in background) but not closed by system, everything works fine.
I also tryed to override onSaveInstanceState() and onRestoreInstanceState() with nothing to be saved and restored (no call to super implementation), but it had no effect.
I'm using Android 4.1.1 and emulator 2.1.
Does anyone have any idea?
Thanks Ales
Here are (links to) screenshots to figure it out better:
Before activity is closed by system
After activity is recreated
Here are the layout files:
<!-- Header -->
<LinearLayout
android:id="#+id/startlistHeaderLayout" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView android:id="#+id/textStartlistName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:gravity="left"
android:text=""
/>
<TextView android:id="#+id/textStarttime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:gravity="right"
android:text=""
android:layout_weight="1"
/>
</LinearLayout>
<!-- Results -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/resultsScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:saveEnabled="false"
>
<TableLayout
android:id="#id/timingLapTableLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="2"
android:shrinkColumns="2"
android:saveEnabled="false"
>
<!-- rows are added in code -->
</TableLayout>
</ScrollView>
</LinearLayout>
<!-- R.layout.timing_row -->
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/timingTableRow"
android:saveEnabled="false"
>
<TextView
android:id="#id/textTimingPosition"
android:text=""
android:gravity="right"
android:paddingLeft="4dip"
android:saveEnabled="false"
/>
<TextView
android:id="#id/textTimingBib"
android:text=""
android:gravity="right"
android:paddingLeft="1dip"
android:saveEnabled="false"
/>
<TextView
android:id="#id/textTimingName"
android:text=""
android:lines="1"
android:ellipsize="end"
android:gravity="left"
android:paddingLeft="1dip"
android:paddingRight="5dip"
android:saveEnabled="false"
/>
<TextView
android:id="#id/textTimingBehind1"
android:text=""
android:gravity="right"
android:paddingRight="5dip"
android:saveEnabled="false"
/>
<TextView
android:id="#id/textTimingBehind2"
android:text=""
android:gravity="right"
android:paddingRight="5dip"
android:saveEnabled="false"
/>
</TableRow>
Here is part of Activity code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
loadPreferencesTimingTheme();
if (ownTheme) {
this.setTheme(theme);
} else {
this.setTheme(MainActivity.theme);
}
}
protected void onStart() {
super.onStart();
View lapView;
View v;
int sid;
setContentView(R.layout.startlist_edit);
sid = getIntent().getIntExtra(TimingActivity.STARTLIST_ID, -1);
if (sid == -1) {
Toast.makeText(this, "Sorry, could not load startlist.", Toast.LENGTH_LONG);
this.finish();
return;
}
tdb = new TimingDB(this);
sl = tdb.getStartlist(sid); // get Startlist from db into memory
// hide unnecessary columns
v = findViewById(R.id.timingLapTableLayout);
((TableLayout) v).setColumnCollapsed(0, true);
loadStartlist(sl); // inflate rows with startlist data and set listeners
// load the preferences and set preferences listener
loadPreferences();
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(prefsChangeListener);
}
public void onStop() {
super.onStop();
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(prefsChangeListener);
if (tdb != null) tdb.close();
}
protected void onSaveInstanceState (Bundle outState) {
// super.onSaveInstanceState(outState);
}
protected void onRestoreInstanceState (Bundle savedInstanceState) {
// super.onRestoreInstanceState(savedInstanceState);
}
protected void onDestroy() {
super.onDestroy();
if (tdb != null) tdb.close();
}
private void loadStartlist(StartList sl) {
// set startlist name & time
View v = findViewById(R.id.textStarttime);
((TextView) v).setText(SimpleDateFormats.ddmmyyyyhhmmss.format(new Date(sl.getStartTime())));
v = findViewById(R.id.textStartlistName);
((TextView) v).setText(sl.getName());
// set header onclicklistener
v = findViewById(R.id.startlistHeaderLayout);
v.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// show dialog to change startlist name and time
Bundle args = new Bundle();
args.putString(KEY_NAME, ((TextView) findViewById(R.id.textStartlistName)).getText().toString());
args.putString(KEY_STTIME, ((TextView) v.findViewById(R.id.textStarttime)).getText().toString());
if (Build.VERSION.SDK_INT < 8) {
dialogBundle = args;
showDialog(DIALOG_EDIT_STARTLIST);
} else {
showDialog(DIALOG_EDIT_STARTLIST, args);
}
}
});
// add competitors to startlist
int cnt = sl.getCompetitorsCount();
for (int i = 0; i < cnt; i++) {
Competitor c = sl.getCompetitorByIndex(i);
appendStartlistRow(c);
}
}
public void appendStartlistRow(final Competitor c) {
TableRow inflatedView = (TableRow) getLayoutInflater().inflate(R.layout.timing_row, null);
inflatedView.setTag(TAG_COMPETITOR, c);
inflatedView.setTag(new Integer(c.getBib()));
inflatedView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TableLayout tl = (TableLayout) findViewById(R.id.timingLapTableLayout);
Bundle args = new Bundle();
args.putInt(KEY_INDEX, tl.indexOfChild(v));
if (Build.VERSION.SDK_INT < 8) {
dialogBundle = args;
showDialog(DIALOG_EDIT_COMPETITOR);
} else {
showDialog(DIALOG_EDIT_COMPETITOR, args);
}
}
});
// set up texts
TextView text = (TextView) inflatedView.findViewById(R.id.textTimingBib);
text.setText(c.getBib() + "");
text = (TextView) inflatedView.findViewById(R.id.textTimingName);
text.setText(c.getName());
text = (TextView) inflatedView.findViewById(R.id.textTimingBehind1);
text.setText(getFormatedStartTime(sl, c, Settings.STARTTIME_ABSOLUTE));
text = (TextView) inflatedView.findViewById(R.id.textTimingBehind2);
text.setText(getFormatedStartTime(sl, c, Settings.STARTTIME_RELATIVE));
// append the row
appendStartlistRow((ViewGroup) inflatedView);
}
public void appendStartlistRow(ViewGroup row) {
// set background and text colors
if (((((Integer) row.getTag()).intValue()) % 2) == Defs.VIEW_EVEN) {
row.setBackgroundColor(Defs.COLOR_BACKGROUND_EVEN);
for (int j = 0; j < row.getChildCount(); j++) {
((TextView) (row.getChildAt(j))).setTextColor(Defs.COLOR_TEXT_EVEN);
}
} else {
row.setBackgroundColor(Defs.COLOR_BACKGROUND_ODD);
for (int j = 0; j < row.getChildCount(); j++) {
((TextView) (row.getChildAt(j))).setTextColor(Defs.COLOR_TEXT_ODD);
}
}
((TableLayout) findViewById(R.id.timingLapTableLayout)).addView(row);
}
Defs.java:
public class Defs {
protected static final int VIEW_EVEN = 0;
protected static final int VIEW_ODD = 1;
protected static int COLOR_BACKGROUND_EVEN;
protected static int COLOR_BACKGROUND_ODD;
protected static int COLOR_BACKGROUND_SELECTED;
protected static int COLOR_BACKGROUND_SPYED;
protected static int COLOR_TEXT_ODD;
protected static int COLOR_TEXT_EVEN;
protected static int COLOR_TEXT_SELECTED;
protected static int COLOR_TEXT_SPYED;
private static boolean isInitialized = false;
protected static void init(Context c) {
if (isInitialized) return;
COLOR_BACKGROUND_EVEN = c.getResources().getColor(R.color.background_darker);
COLOR_BACKGROUND_ODD = c.getResources().getColor(R.color.background_lighter);
COLOR_BACKGROUND_SELECTED = c.getResources().getColor(R.color.background_selected);
COLOR_BACKGROUND_SPYED = c.getResources().getColor(R.color.background_spyed);
COLOR_TEXT_ODD = c.getResources().getColor(R.color.text_lighter);
COLOR_TEXT_EVEN = c.getResources().getColor(R.color.text_darker);
COLOR_TEXT_SELECTED = c.getResources().getColor(R.color.text_selected);
COLOR_TEXT_SPYED = c.getResources().getColor(R.color.text_spyed);
isInitialized = true;
}
}
Without any code it's next to impossible to say much about the problem itself. But I did want to say (would fit better as a comment but can't do it yet) that for a long list (like yours seems to be based on the screenshots) using an actual ListView with a custom ArrayAdapter might be a better solution. ListView re-uses views when scrolled thus reducing unnecessary view creation. Also, once you learn how to use the ListView, you'll probably find it easier than adding table rows manually. If those aren't familiar to you, check a tutorial here:
http://www.vogella.com/articles/AndroidListView/article.html
And if you decide to change from tables to a ListView, maybe the problem (whatever it is) disappears as well. You never know. :)
Related
I have a button inside a view that checks some constraints, and then starts another activity, however the startActivity() call does not do anything, the new activity's onCreate() never gets called, and the code then continues past it. I have checked using logging and breakpoints, and the conditions are being met and startActivity() is being called. Both activities are defined in the application manifest.
From the source activity's onCreate():
int[] winning_player;
int next_player;
int[] scores;
[...]
final Button end_turn_button = (Button) findViewById(R.id.end_turn);
end_turn_button.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (winning_player[0] == next_player) {
Intent intent = new Intent(getApplicationContext(), FinalScreenActivity.class);
intent.putExtra("SCORES", scores);
startActivity(intent);
}
}
});
FinalScreenActivity.java
public class FinalScreenActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_final_screen);
Intent intent = getIntent();
final int[] scores = intent.getIntArrayExtra("SCORES");
// put the scoreboard in ascending order
Arrays.sort(scores);
// find the scoreboard in the view
TableLayout scoreboard = (TableLayout) findViewById(R.id.scoreboard);
// get the string resources to be formatted
Resources res = getResources();
String player_name_format = res.getString(R.string.player);
// Set the scoreboard in the view
Log.d("brains.PlayActivity", "onCreate: Creating scoreboard");
// for each player entry in the scoreboard
for (int i = 0; i < scores.length; i++) {
Log.d("brains.PlayActivity", "onCreate: adding scoreboard entry "+String.valueOf(i));
// create 2 TextViews
TextView player_name = new TextView(FinalScreenActivity.this);
TextView player_score = new TextView(FinalScreenActivity.this);
// Set the size of the TextViews
player_name.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
// set the first one to the player's name string resource
player_name.setText(String.format(player_name_format, i + 1));
// set the second one to the player's score resource, which takes the score twice (once for the number itself, and once to work out which plural is needed)
player_score.setText(res.getQuantityString(R.plurals.brains, scores[i], scores[i]));
// Create a TableRow to put the score into
TableRow scoreboard_entry = new TableRow(FinalScreenActivity.this);
// Set the size of the TableRow
scoreboard_entry.setLayoutParams(new TableRow.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
// Add the TextViews to the TableRow
scoreboard_entry.addView(player_name);
scoreboard_entry.addView(player_score);
// Add the TableRow to the TableLayout
scoreboard.addView(scoreboard_entry);
}
// Get the title text
TextView title_text = (TextView) findViewById(R.id.title_text);
title_text.setText(res.getQuantityString(R.plurals.win_brains, scores[scores.length - 1], scores.length - 1, scores[scores.length - 1]));
// set the play again button
Button play_again_button = (Button) findViewById(R.id.play_again_button);
play_again_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(), SelectPlayersActivity.class);
startActivity(intent);
}
});
}
}
and activity_final_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="uk.co.bluesapphiremedia.android.zombiedice.FinalScreenActivity"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/title_text"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:id="#+id/scoreboard"
android:layout_below="#+id/title_text" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/play_again"
android:id="#+id/play_again_button"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true" />
</RelativeLayout>
end_turn_button.setOnClickListener(this);
//override onClick() method in activity implement interface View.OnClickListner
public void onClick(View v) {
if(v.getId() == R.id.end_turn){
if (winning_player[0] == next_player) {
Intent intent = new Intent(this,FinalScreenActivity.class);
intent.putExtra("SCORES", scores);
startActivity(intent);
}
}
}
I have horizontal scrollview in my android app with Next and Previous buttons.I want to show the these buttons only when the scollview needs scrolling.ie,width of scrollview content exceeds display width.Also want to hide previous and Next buttons when reaching first and last items respectively.How to to next/previous items when click on these buttons?
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffffff" >
<Button
android:id="#+id/btnPrevoius"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Previous"
android:visibility="gone" />
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_toLeftOf="#+id/btnNext"
android:layout_toRightOf="#+id/btnPrevoius"
android:fillViewport="true" >
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
<Button
android:id="#+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="Next"
android:visibility="gone" />
</RelativeLayout>
activity
public class SampleActivity extends Activity {
private static LinearLayout linearLayout;
private static HorizontalScrollView horizontalScrollView;
private static Button btnPrevious;
private static Button btnNext;
private static int displayWidth = 0;
private static int arrowWidth = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontalScrollView1);
linearLayout = (LinearLayout) findViewById(R.id.linearLayout1);
btnPrevious = (Button) findViewById(R.id.btnPrevoius);
btnNext = (Button) findViewById(R.id.btnNext);
for (int i = 0; i < 15; i++) {
Button button = new Button(this);
button.setTag(i);
button.setText("---");
linearLayout.addView(button);
}
ViewTreeObserver vto = linearLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewTreeObserver obs = linearLayout.getViewTreeObserver();
obs.removeGlobalOnLayoutListener(this);
Display display = getWindowManager().getDefaultDisplay();
displayWidth = display.getWidth();
if (linearLayout.getMeasuredWidth() > (displayWidth - 40)) {
btnPrevious.setVisibility(View.VISIBLE);
btnNext.setVisibility(View.VISIBLE);
}
}
});
btnPrevious.setOnClickListener(listnerLeftArrowButton);
horizontalScrollView.setOnTouchListener(listenerScrollViewTouch);
}
private OnTouchListener listenerScrollViewTouch = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
showHideViews();
return false;
}
};
private OnClickListener listnerLeftArrowButton = new OnClickListener() {
#Override
public void onClick(View v) {
horizontalScrollView.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(0, 0));
}
};
public static void showHideViews() {
int maxScrollX = horizontalScrollView.getChildAt(0).getMeasuredWidth()- displayWidth;
Log.e("TestProjectActivity", "scroll X = " +horizontalScrollView.getScrollX() );
Log.i("TestProjectActivity", "scroll Width = " +horizontalScrollView.getMeasuredWidth() );
Log.d("TestProjectActivity", "Max scroll X = " + maxScrollX);
if (horizontalScrollView.getScrollX() == 0) {
hideLeftArrow();
} else {
showLeftArrow();
}
if (horizontalScrollView.getScrollX() == maxScrollX) {
showRightArrow();
} else {
//hideRightArrow();
}
}
private static void hideLeftArrow() {
btnPrevious.setVisibility(View.GONE);
}
private static void showLeftArrow() {
btnPrevious.setVisibility(View.VISIBLE);
}
private static void hideRightArrow() {
btnNext.setVisibility(View.GONE);
}
private static void showRightArrow() {
btnNext.setVisibility(View.VISIBLE);
}
}
The 'maxScrollX' value is not correct for me.How to find maximum scrollvalue for this?
Thanks in Advance
This might come a bit late, but for anyone out there that will face this problem I suggest alternative solution(s).
First, use different component than HorizontalScrollView. Here are the options:
OPTION 1: Horizontal ListView - add this class to your project (create a separate package, something like com.yourproject.widgets). Also you'll need to create custom Adapter, see how that's done in this example. I suggest you create separate adapter class (exp. HorizontalListViewAdapter) and put it in already created com.yourproject.widgets package.
add this widget to your layout in the xml (put it between buttons that need to mimic the scrolling behavior) you'll need to add something like:
<com.yourproject.widgets.HorizontalListView
android:id="#+id/hList"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
reference this (along with the buttons) in the Activity/Fragment that utilizes the widget
HorizontalListView mHList = (HorizontalListView) findViewById (R.id.hList);
Button bPrevoius = (Button) findViewById (R.id.btnPrevoius);
Button bNext = (Button) findViewById (R.id.btnNext);
add onClickListeners to the Buttons. Use the scrollTo() function predefined in the HorizontalListView widget. As you can see in the code, it takes int dp value to scroll. Add positive values if you want to scroll in right (next), and use negative values if you want to scroll in left (previous):
bPrevoius.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//value 500 is arbitrarily given. if you want to achieve
//element-by-element scroll you should get the width of the
//previous element dynamically or if the elements of the
//list have uniform width just put that value instead
mHList.scrollTo(-500);
//if it's the first/last element you can bPrevoius.setEnabled(false)
}
});
bNext.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mHList.scrollTo(500);
}
});
OPTION 2: More up to date solution to this issue can be the new widget RecyclerView introduced in Android L (addition of android:scrollbars="vertical" seems that would do the trick; other than that should have conventional ListView behavior). For more info check the official documentation.
devu
Plz have a look at the following links
1) http://android-er.blogspot.in/2012/07/implement-gallery-like.html
2) http://androiddreamers.blogspot.in/2012/09/horizontal-scroll-view-example.html
3)http://code.google.com/p/mobyfactory-uiwidgets-android/
Let me know if u r facing any issues
Thanks
In titanium appcelerator, you can do this using scrollableView
var scrollableView = Ti.UI.createScrollableView({
showPagingControl:true,
scrollingEnabled: true,
top: 360
});
Then, you can run a loop of all images or any content that you have, and add them to this view.
for(loop) {
eval("var view"+i+"=Ti.UI.createView();");
profile_image = Ti.UI.createImageView({
image: result[0]['profile_image'],
left:15,
width:82,
height:104,
top: 0
});
eval("view"+i+".add(profile_image);");
eval("scrollableView.addView(view"+i+");");
}
mywin.add(scrollableView);
I am developing a kind of memory game app, where initially the 6 buttons will show some figures. Then when the below MyCount5sec and handler operates, after 5 sec of waiting period for user to remember, the handler will invoke txtClearRun whereby all the texts on every buttons to be erased.
Then after the 5 sec waiting period, it comes the testing period. The user has to select the button in sequence, ie. the latter button value must need to be greater than the earlier button value.
If the user is sucessful (ie. pressed all 6 number buttons), the app should wait 1.5 sec according to postDelay? Yet it appears that there are no delays.
If the user is wrong, ie. pressed button with value smaller than the previous one, the user fails and the app should also wait 1.5sec, with the button highlighted in red. However, it seems that there are no such 1.5sec delay too. No highlighting in red neither.
Question
Why there appears no delays? TWO handlers cannot be invoked at the same time?
how could that be further modified?
Thanks a lot!!
private void setQup()
{
.....
MyCount5sec counter5sec = new MyCount5sec(6000,1000);
counter5sec.start();
handler.postDelayed(txtClearRun, 6000);
pressed = 0;
temp = 0;
final int txtClearRun1time = 1500; // set here!
button_space1.setText("reset press "+pressed);
Button11.setOnClickListener(new OnClickListener() {#Override
public void onClick(View v) {vibrate(); int i=0; Button11.setEnabled(false);
if (i == B0) {puttobutton(B0,0);} if (i == B1) {puttobutton(B1,1);} if (i == B2) {puttobutton(B2,2);}
if (i == B3) {puttobutton(B3,3);} if (i == B4) {puttobutton(B4,4);} if (i == B5) {puttobutton(B5,5);}
pressed = pressed + 1;
int buttonvalue = Integer.parseInt(Button11.getText().toString());
if (pressed >5)
{
TotalScores=TotalScores+20;
handler1.postDelayed(txtClearRun1, txtClearRun1time);
loadNextQup();
}
if (buttonvalue < temp)
{
Button11.setBackgroundResource(R.drawable.red_btn);
TotalScores=TotalScores-10;
handler1.postDelayed(txtClearRun1, txtClearRun1time);
loadNextQup();
}
temp = buttonvalue;
}});
......same for other buttons..
}
Runnable txtClearRun = new Runnable()
{
public void run() {blankbutton();} //remove text on buttons
};
Runnable txtClearRun1 = new Runnable()
{
public void run() {} // solely for wish to delay operations
};
private void loadNextQup()
{
if (TerminateOrNot ==0)
{
handler.removeCallbacks(txtClearRun);
handler1.removeCallbacks(txtClearRun1);
setQup();
}
....
}
I tried make a simple game working on your rules ;) Instead of shapes I used checking background colors and text. I hope you will understand it, maybe this will help you some.
This is full working project:
Class:
public class MainActivity extends Activity {
Button bt1, bt2, bt3, bt4, bt5, bt6, bt7, bt8, bt9, restart;
List<Button> listButtons;
Handler handler1;
List<Integer> buttonColors;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listButtons = new ArrayList<Button>();
listButtons.add(bt1 = (Button) findViewById(R.id.bt1));
listButtons.add(bt2 = (Button) findViewById(R.id.bt2));
listButtons.add(bt3 = (Button) findViewById(R.id.bt3));
listButtons.add(bt4 = (Button) findViewById(R.id.bt4));
listButtons.add(bt5 = (Button) findViewById(R.id.bt5));
listButtons.add(bt6 = (Button) findViewById(R.id.bt6));
listButtons.add(bt7 = (Button) findViewById(R.id.bt7));
listButtons.add(bt8 = (Button) findViewById(R.id.bt8));
listButtons.add(bt9 = (Button) findViewById(R.id.bt9));
setAllEnabled(false);
// add on click listeners
for (int i = 0; i < listButtons.size(); i++) {
final int index = i;
//final because i will need it deeper
final Button s = listButtons.get(i);
//on click
s.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//when user click on something then show the origini color and tap "x"
s.setBackgroundColor(buttonColors.get(index));
s.setText("x");
// get all checked
List<Button> listChecked = countChecked();
// if checked more == 2
if (listChecked.size() == 2) {
// check if the same text was checked
boolean btnsHasTheSameTextAndBackgroundTag = checkAllTextAndBackgroundTag(listChecked);
//if they dont have same color and text then reset them
if (!btnsHasTheSameTextAndBackgroundTag) {
for (Button b : listChecked) {
b.setText("");
b.setBackgroundColor(Color.parseColor("#565656"));
}
}
}
//finall if user clicked 3 the same colors
else if (listChecked.size() == 3) {
// check if the same text was checked
boolean btnsHasTheSameTextAndBackgroundTag = checkAllTextAndBackgroundTag(listChecked);
if (btnsHasTheSameTextAndBackgroundTag) {
for (Button b : listChecked) {
b.setVisibility(View.INVISIBLE);
b.setText("");
}
} else {
for (Button b : listChecked)
{b.setText("");
b.setBackgroundColor(Color.parseColor("#565656"));
}
}
}
}
private boolean checkAllTextAndBackgroundTag(List<Button> list) {
int number = (Integer) list.get(0).getTag();
for (Button b : list) {
// if one of them will fail
if (!b.getText().equals("x") || number != (Integer)b.getTag())
return false;
}
return true;
}
private List<Button> countChecked() {
List<Button> temp = new ArrayList<Button>();
for (Button b : listButtons) {
if (b.getText().equals("x"))
temp.add(b);
}
return temp;
}
});
}
restart = (Button) findViewById(R.id.bt_restart);
// we go on.. create list of colors
final List<Integer> colorList = new ArrayList<Integer>();
colorList.add(Color.parseColor("#C3C3E5"));
colorList.add(Color.parseColor("#F1F0FF"));
colorList.add(Color.parseColor("#8C489F"));
// on restart button action
restart.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//enable all
setAllEnabled(true);
// remember new colors and create for it container
buttonColors = new ArrayList<Integer>();
// create random
Random r = new Random();
// get temp counter used colors
int[] wastedColor = new int[colorList.size()];
// for all buttons do the same job
for (int i = 0; i < listButtons.size(); i++) {
Log.d("xxx", i + "");
// take first random number
int numberRandom = r.nextInt(colorList.size());
// check if we have all colors with the same amount
while (wastedColor[numberRandom] == colorList.size())
numberRandom = r.nextInt(colorList.size());
// increment existing ones
wastedColor[numberRandom]++;
// remmeber this color
buttonColors.add(colorList.get(numberRandom));
listButtons.get(i).setTag(numberRandom);
listButtons.get(i).setBackgroundColor((int) (colorList.get(numberRandom)));
listButtons.get(i).setVisibility(View.VISIBLE);
}
// after generated colors...
handler1 = new Handler();
// hide after 5 sec
handler1.postDelayed(new HideAllColors(), 5000);
}
});
}
private void setAllEnabled(boolean status) {
for(Button b : listButtons)
b.setEnabled(status);
}
private class HideAllColors implements Runnable {
#Override
public void run() {
for (Button b : listButtons)
b.setBackgroundColor(Color.parseColor("#565656"));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<Button
android:id="#+id/bt1"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:background="#565656" />
<Button
android:id="#+id/bt2"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_toRightOf="#+id/bt1"
android:background="#565656" />
<Button
android:id="#+id/bt3"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_margin="5dp"
android:layout_toRightOf="#+id/bt2"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt4"
android:layout_below="#+id/bt1"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt5"
android:layout_below="#+id/bt2"
android:layout_toRightOf="#+id/bt4"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt6"
android:layout_below="#+id/bt3"
android:layout_toRightOf="#+id/bt5"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt7"
android:layout_below="#+id/bt4"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt8"
android:layout_below="#+id/bt5"
android:layout_toRightOf="#+id/bt7"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt9"
android:layout_below="#+id/bt6"
android:layout_toRightOf="#+id/bt8"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="#565656" />
<Button
android:layout_margin="5dp"
android:id="#+id/bt_restart"
android:text="restart"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#565656" />
</RelativeLayout>
I have an application on which I apply some resources to buttons to modify their backgrounds.
All work well, but when my application goes to onResume after onPause, I'm not able to set the background anymore.
I have a set of 18 buttons, and when I am in onResume, i call:
for (int i = 0; i < max; i++) {
Button b = l.get(i);
b.setBackgroundResource(R.color.green);
}
In l i have the list of all buttons got from findViewById().
This works only for the last element of the for, but not for the others.
Any idea?
** Edit **
This is the code I use for populating the array
btn_1 = (Button)findViewById(R.id.btn_1);
btn_1.setOnClickListener(this);
l.add(btn_1);
this is repeated for all my buttons.
** Second edit **
public void onResume() {
btn_1 = (Button)findViewById(R.id.btn_1);
btn_1.setOnClickListener(this);
l = new ArrayList<Button>();
l.add(btn_1);
...
for (int i = 0; i < max; i++) {
Button b = l.get(i);
b.setBackgroundResource(R.color.green);
}
}
The same is done in onCreate().
try the d following.. this will works fine.
List<Button> mButtonList = new ArrayList<Button>();
onCreate() {
mButtonList.add((Button) findViewById(R.id.btn_1));
mButtonList.add((Button) findViewById(R.id.btn_2));
mButtonList.add((Button) findViewById(R.id.btn_3));
....
for(Button b : mButtonList) {
b.setOnClickListener(this);
}
}
onResume() {
for(Button b : mButtonList) {
b.setBackgroundResource(R.color.green);
}
}
Simple example:
Activity
public class StackOverFlowActivity extends Activity {
private ArrayList<Button> myArray = new ArrayList<Button>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myArray.add((Button)findViewById(R.id.btn_1));
myArray.add((Button)findViewById(R.id.btn_2));
myArray.add((Button)findViewById(R.id.btn_3));
myArray.add((Button)findViewById(R.id.btn_4));
myArray.add((Button)findViewById(R.id.btn_5));
}
#Override
protected void onResume() {
super.onResume();
for (Button b : myArray) {
b.setBackgroundColor(getResources().getColor(R.color.blue));
}
}
}
XML main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1" />
<Button
android:id="#+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2" />
<Button
android:id="#+id/btn_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 3" />
<Button
android:id="#+id/btn_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 4" />
<Button
android:id="#+id/btn_5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 5" />
</LinearLayout>
My color in the Strings.xml
<color name="blue">#0099CC</color>
Use this instead:
for (int i = 0; i < max; i++) {
Button b = l.get(i);
b.setBackgroundColor(getResources().getColor(R.color.green));
}
If max is really big you might want to cache the getColor result before the loop.
EDIT:
According to the docs: setBackgroundResource is to be used with drawable ids only, and setBackgroundColor seems to be exactly what you need, so maybe another part of your code isn't working well, maybe the loop, the above line for setBackgroundColor works well on my app.
You've said:
": the ... code is the same for btn_1, just swap btn_1 with btn_2, btn_3 and so on. "
if so, than these lines are resetting your Array every time you try and add a new button.
l = new ArrayList<Button>();
l.add(btn_1);
P.S. you should avoid using a manual creation of buttons array - instead use some Parenting Layout such as LinearLayout and then fetch his button son's using getChildAt(i), It's much cleaner. Example:
// Register all the buttons in the layout to the OnClickListener
LinearLayout lin = (LinearLayout)findViewById(R.id.linear_buttons);
int childcount = lin.getChildCount();
for (int i=0; i < childcount; i++){
View v = lin.getChildAt(i);
v.setOnClickListener(this);
}
Try this --
for (int i = 0; i < l.getChildCount(); i++)
{
Button b = (Button) l.getChildAt(i);
b.setBackgroundResource(R.color.green);
}
try this. its working for me
for (int i = 0; i < count; i++) {
btn_title[i] = new Button(ActivityName.this);
btn_title[i].setText(menu.menu_title[i]);
btn_title[i].setId(i);
btn_title[i].setTextColor(Color.BLACK);
btn_title[i].setBackgroundColor(Color.parseColor(dataxml
.getMenucolor()));
btn_title[i]
.setTextSize(Integer.parseInt(dataxml.getFontsize()));
btn_title[i].setGravity(Gravity.CENTER_VERTICAL
| Gravity.CENTER_HORIZONTAL);
btn_title[i].setSingleLine();
btn_title[i].setEllipsize(TruncateAt.END);
btn_title[i].setOnClickListener(new ButtonListner());
}
hope this will help
why don't extend Button class, set its color, then use that new class?
It wont work obviously , let me explain why it has set last value of button .
you are using of one button reference (whatever u got from (Button)findViewById(R.id.btn_1) )
and untimely there is a one button reference and u just change its value using l.add(btn_1);
what you need to do is , do create a new button instance for each button and inflate it in proper view .
here is the small tick for that
for (int i==0 ; i < length; i++ ){
Button button = new Button(context);
collectionOfButton.add(button) ;
}
use that buttons collection using inflate if u try to integrate in some xml layout file .
I want to get the id's of my imageviews in my ObjectsClass which are in level1.xml and I have inflated this layout in GamePlayActivity...MY ObjectClass is not activity then how to get array of id's in that class ...here is my level.xml say there are 15 ImageView I have just shown few ....
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#drawable/gmw_01"
android:onClick="onClick"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/relativeLayout1" >
<ImageView
android:onClick="objectClick"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/imageView1"
android:src="#drawable/bb01"
android:layout_marginLeft="998dp"
android:layout_marginTop="593dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<ImageView
android:onClick="objectClick"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/imageView2"
android:src="#drawable/bb02"
android:layout_marginLeft="20dp"
android:layout_marginTop="39dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
<ImageView
android:onClick="objectClick"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="#+id/imageView3"
android:src="#drawable/bb03"
android:layout_marginLeft="497dp"
android:layout_marginTop="153dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"/>
and here is my GameplayActivity
public class GamePlayActivity extends Activity {
static int ObjectsFound;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameplay);
// ViewGroup where n number of view is going to added
ViewGroup layout= (ViewGroup) findViewById(R.id.GamePlayScreen);
// inflating the layout depending on the level
View level = View.inflate(this, LevelSelectionActivity.levelscreen, null);
** getRandom(); // here I want to call that random because this should be done before my level is added on the view**
// adding level bg for the respective selected level
layout.addView(level);
}
public void objectClick(View objectClicked)
{
Toast msg;
int Object = objectClicked.getId();
ImageView img= (ImageView)findViewById(objectClicked.getId());
switch (Object) {
case R.id.imageView1:
img.setVisibility(View.INVISIBLE);
msg = Toast.makeText(GamePlayActivity.this, "Bubble Found", Toast.LENGTH_SHORT);
msg.setGravity(Gravity.CENTER, msg.getXOffset() / 2, msg.getYOffset() / 2);
msg.show();
break;
}
}
and the ObjectClass
public class Objects {
int ObectId[];
Objects(Context context)
{
super();
for(int i=0;i<15;++i)
{
**ObectId[i]=R.id.;** // what to get it over here ? ? ?
}
}
public void randomize() {
Random generator = new Random();
for(int i = 0; i<8 ; i++) {
while(true) {
**View v = findViewById(generator.nextInt(Objectid.length));**
if(!v.isClickable()) {
v.setClickable(false);
break;
}
}
}
}
}
at the end I want random number of objects to be unclickable i.e. out of 15 objects everytime user can have only 8 objects clickable on the screen so before my level starts i.e. before I inflate in my gameplayActivity as seen above I want to get random 8 clickable and vice versa...
Adding to that it should work for all level ...right now I have one level1.xml how to achieve it for all levels... do i need to give same id's of image view in all layout ?
Sure you can, all you need to do is make the ImageView with the same id name, then you can always access them with the same int id.
Don't forget to re-init them after load new layout.
try some thing like this
int resA = getResources().getIdentifier("your image view", "your layout", getPackageName());
hope this help..
Are there any views inside that RelativeLayout besides each ImageView you're interested in? If not, just use the getChildCount() and getChildAt() methods on the layout to obtain the views you need. Any ViewGroup already stores its children in an array, so there's no reason to duplicate the behavior if those are the only views contained there:
//Somewhere in your code get a reference to the layout
RelativeLayout layout = (RelativeLayout)findViewById(R.id.relativeLayout1);
//Then, update your view selection line like so
**View v = layout.getChildAt(generator.nextInt(layout.getChildCount()));**
HTH