Runtime Error, by starting the Application [duplicate] - android

This question already has answers here:
How to set Id of dynamic created layout?
(10 answers)
Closed 5 years ago.
I have written a small app in Android Studio. If I start the app in the emulator, then I get an exception. The application simply stops.
The source code looks as follows:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private int points, round, countdown;
private static final int FROG_ID = 212121;
private Random rnd = new Random();
private Handler handler = new Handler();
private Runnable runnable = new Runnable(){
#Override
public void run(){
countdown();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//newGame();
showStartFragment();
}
private void newGame(){
points = 0;
round = 1;
initRound();
}
private void initRound(){
countdown = 10;
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
WimmelView wv = new WimmelView(this);
container.addView(wv, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
wv.setImageCount(5*(10+round));
ImageView frog = new ImageView(this);
frog.setId(FROG_ID);
frog.setImageResource(R.drawable.frog1);
frog.setScaleType(ImageView.ScaleType.CENTER);
float scale = getResources().getDisplayMetrics().density;
FrameLayout.LayoutParams lp= new FrameLayout.LayoutParams(Math.round(64*scale),Math.round(61*scale));
lp.leftMargin = rnd.nextInt(container.getWidth()-64);
lp.topMargin = rnd.nextInt(container.getHeight()-61);
lp.gravity = Gravity.TOP + Gravity.START;
frog.setOnClickListener(this);
container.addView(frog, lp);
handler.postDelayed(runnable, 1000-round*50);
update();
}
private void fillTextView(int id, String text){
TextView tv = (TextView) findViewById(id);
tv.setText(text);
}
private void update(){
fillTextView(R.id.points, Integer.toString(points));
fillTextView(R.id.round, Integer.toString(round));
fillTextView(R.id.countdown,
Integer.toString(countdown*1000));
}
private void showStartFragment(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.removeAllViews();
container.addView(
getLayoutInflater().
inflate(R.layout.fragment_start, null));
container.findViewById(R.id.start).setOnClickListener(this);
}
private void showGameOverFragment(){
ViewGroup container = (ViewGroup) findViewById(R.id.container);
container.addView(
getLayoutInflater().
inflate(R.layout.fragment_gameover, null));
container.findViewById(play_again).setOnClickListener(this);
}
#Override
public void onClick(View view) {
if(view.getId()==R.id.start){
startGame();
}else if(view.getId()==R.id.play_again){
showStartFragment();
}else if(view.getId()==FROG_ID){
handler.removeCallbacks(runnable);
Toast.makeText(this,R.string.kissed, Toast.LENGTH_SHORT).show();
//showToast(R.string.kissed);
points += countdown*1000;
round++;
}
initRound();
}
private void startGame() {
newGame();
}
private void countdown(){
countdown--;
update();
if(countdown<=0){
//frog.setOnClickListener(null);
showGameOverFragment();
}else {
handler.postDelayed(runnable, 1000-round*50);
}
}
#Override
protected void onPause(){
super.onPause();
handler.removeCallbacks(runnable);
}
}
At the beginning I came so far that I could at least press on start, now I am not at all more in the application pure ...
I have tried to googlen what it could be, but I have not succeeded in doing so. I also get a error message at the point frog.setId (FROG_ID).
In addition, I have yet another class, which implements images
public class WimmelView extends View {
private Random rnd;
private long randomSeed = 1;
private int imageCount;
private Paint paint = new Paint();
private static final int[]
images = { R.drawable.frog2,
R.drawable.frog3,R.drawable.frog4,
R.drawable.frog5,R.drawable.frog6};
public void setImageCount(int imageCount){
this.imageCount = imageCount;
randomSeed = System.currentTimeMillis();
invalidate();
}
public WimmelView(Context context){
super(context);
paint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
rnd = new Random(randomSeed);
for(int image:images){
Bitmap bitmap =
BitmapFactory.decodeResource(getResources(),image);
for(int i=0; i<imageCount/images.length; i++){
float left = (float) (rnd.nextFloat()
*(getWidth()-bitmap.getWidth()));
float top = (float) (rnd.nextFloat()
*(getWidth()-bitmap.getWidth()));
canvas.drawBitmap(bitmap,left,top,paint);
}
bitmap.recycle();
}
}
}
I hope someone sees the error and can help me ...

Your error is that the Content view is removing all children from the screen including the textviews of the score and points that you are trying to use. I just helped you move to fragments offline and ensured you were good to go. Goodluck.

You can use this,
<item name="frog_id" type="id"/>
This give you unique value.
You add this in your ids.xml. and change your code
...
frog.setId(R.id.frog_id);
...
else if(view.getId()==R.id.frog_id)
Try this

This is related to setting the view id. You can't set the id with the following:
private static final int FROG_ID = 212121;
...
frog.setId(FROG_ID);
You need to define an id in res/values/ids.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="your_view_id" type="id"/>
</resources>
But this will against the purpose of creating a dynamic view.
Instead, you can use View.generateViewId for the id instead. But please remember that this method only work from API version 17. Here the excerpt:
int generateViewId ()
Generate a value suitable for use in setId(int). This value will not
collide with ID values generated at build time by aapt for R.id.

Related

Android: dynamically create matrix of editText based on user input?

I'm new to android development. I've noticed some similar questions but none of them really answered my question well enough that I could figure it out, or else they relied upon depreciated functions.
So far, I've created my main class. I want to open to a screen where the user inputs two numbers for the row and column length of a matrix they want to reduce
public class MainActivity extends AppCompatActivity {
public int numberOfRows;
public int numberOfColumns;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setRows(View v3) {
EditText editTextRow = (EditText) findViewById(R.id.editText2);
if ("".equals(editTextRow.getText())) {
}
else {
numberOfRows = Integer.parseInt(editTextRow.getText().toString());
}
}
public void setColumns(View v2) {
EditText editTextCol = (EditText) findViewById(R.id.editText3);
if ("".equals(editTextCol.getText())) {
numberOfRows = Integer.parseInt(editTextCol.getText().toString());
}
}
public void reduce(View view){
if(numberOfRows != 0 && numberOfColumns != 0) {
}
else {
Intent intent = new Intent(this, ReduceMatrix.class);
Bundle bundle = new Bundle();
bundle.putInt("rows", numberOfRows);
bundle.putInt("cols", numberOfColumns);
intent.putExtras(bundle);
startActivity(intent);
}
}
}
I'm having trouble coming up with the next activity, where I want to dynamically create a matrix of editText...
public class ReduceMatrix extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reduce_matrix);
Intent passedIntent = getIntent();
Bundle extras = passedIntent.getExtras();
int rowNum = extras.getInt("rows");
int colNum = extras.getInt("cols");
Could anyone explain how to go about doing this? I was thinking some sort of for loop, but I have a really hard time with the android layout. Should I be using tableLayout? or gridview? Whenever I have something like
layout = new LinearLayout(this);
It tells me that my qualifier must be in an expression?
You need to add it programmatically. Here's my solution :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent passedIntent = getIntent();
Bundle extras = passedIntent.getExtras();
EditText[][] editTexts = new EditText[rowNum][colNum];
GridLayout gridLayout = new GridLayout(this);
//define how many rows and columns to be used in the layout
gridLayout.setRowCount(rowNum);
gridLayout.setColumnCount(colNum);
for (int i = 0; i < rowNum; i++) {
for (int j = 0; j < colNum; j++) {
editTexts[i][j] = new EditText(this);
setPos(editTexts[i][j], i, j);
gridLayout.addView(editTexts[i][j]);
}
}
setContentView(gridLayout);
}
//putting the edit text according to row and column index
private void setPos(EditText editText, int row, int column) {
GridLayout.LayoutParams param =new GridLayout.LayoutParams();
param.width = 100;
param.height = 100;
param.setGravity(Gravity.CENTER);
param.rowSpec = GridLayout.spec(row);
param.columnSpec = GridLayout.spec(column);
editText.setLayoutParams(param);
}
This will enable you to add EditText(s) dynamically.

Get measure of relative layout android?

I have an empty RelativeLayout. I must get height and width of layout (set to match the parent). I have tried to search online but, to no avail. This is my code, can you help me? When I launch the application it crashes in the getCoordinate method. Sorry for my English.
public class MainActivity extends AppCompatActivity {
Random rand = new Random();
int[] coordinate = new int[2];
public void getCordinate(final RelativeLayout layout){
layout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Ensure you call it only once :
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
coordinate[0] = layout.getMeasuredWidth();// width must be declare as a field
coordinate[1] = layout.getMeasuredHeight();// height must be declare as a fiel
}
});
}
public void makeButton(RelativeLayout play_area){
int button_x = rand.nextInt(coordinate[0]);
int button_y = rand.nextInt(coordinate[1]);
Button bomb = new Button(this);
bomb.setX((float)button_x);
bomb.setY((float)button_y);
play_area.addView(bomb);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout play_area = (RelativeLayout) findViewById(R.id.play_area);
play_area.measure(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
getCordinate(play_area);
Log.d("Coordinate", "Xmax: " + coordinate[0] + " Ymax: " + coordinate[1]);
//makeButton(play_area);
}
}
you shouldn't call measure(). you could maybe just call .setLayoutParams(width, height) to set the view to match parent's width/height.
and simply calling .getMeasuredWidth() (or height) on the view should return their width/height values

Android: Adding functionality that activty changes when game is complete

I wish to add the following functionality to my game:
-When the game is complete (no more cards are visible on screen) then move to a new activity
I am aware how to move to another activty using intents but I am not sure how to implement the functionality in this case.
I.e. what variable/info can I use to ensure the game is complete when I move before moving to the next activity?
For reference, The game is based off this open source game Images of the game are shown here to give an idea.
Current code:
public class Manager extends Activity {
private static int ROW_COUNT = -1;
private static int COL_COUNT = -1;
private Context context;
private Drawable backImage;
private int [] [] cards;
private List<Drawable> images;
private Card firstCard;
private Card seconedCard;
private ButtonListener buttonListener;
private static Object lock = new Object();
int turns;
private TableLayout mainTable;
private UpdateCardsHandler handler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new UpdateCardsHandler();
loadImages();
setContentView(R.layout.main);
TextView url = ((TextView)findViewById(R.id.myWebSite));
Linkify.addLinks(url, Linkify.WEB_URLS);
backImage = getResources().getDrawable(R.drawable.icon);
/*
((Button)findViewById(R.id.ButtonNew)).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
newGame();
}
});*/
buttonListener = new ButtonListener();
mainTable = (TableLayout)findViewById(R.id.TableLayout03);
context = mainTable.getContext();
Spinner s = (Spinner) findViewById(R.id.Spinner01);
ArrayAdapter adapter = ArrayAdapter.createFromResource(
this, R.array.type, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
s.setOnItemSelectedListener(new OnItemSelectedListener(){
#Override
public void onItemSelected(
android.widget.AdapterView<?> arg0,
View arg1, int pos, long arg3){
((Spinner) findViewById(R.id.Spinner01)).setSelection(0);
int x,y;
switch (pos) {
case 1:
x=4;y=4;
break;
case 2:
x=4;y=5;
break;
case 3:
x=4;y=6;
break;
case 4:
x=5;y=6;
break;
case 5:
x=6;y=6;
break;
default:
return;
}
newGame(x,y);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
private void newGame(int c, int r) {
ROW_COUNT = r;
COL_COUNT = c;
cards = new int [COL_COUNT] [ROW_COUNT];
mainTable.removeView(findViewById(R.id.TableRow01));
mainTable.removeView(findViewById(R.id.TableRow02));
TableRow tr = ((TableRow)findViewById(R.id.TableRow03));
tr.removeAllViews();
mainTable = new TableLayout(context);
tr.addView(mainTable);
for (int y = 0; y < ROW_COUNT; y++) {
mainTable.addView(createRow(y));
}
firstCard=null;
loadCards();
turns=0;
((TextView)findViewById(R.id.tv1)).setText("Tries: "+turns);
}
private void loadImages() {
images = new ArrayList<Drawable>();
images.add(getResources().getDrawable(R.drawable.card1));
images.add(getResources().getDrawable(R.drawable.card2));
images.add(getResources().getDrawable(R.drawable.card3));
images.add(getResources().getDrawable(R.drawable.card4));
images.add(getResources().getDrawable(R.drawable.card5));
images.add(getResources().getDrawable(R.drawable.card6));
images.add(getResources().getDrawable(R.drawable.card7));
images.add(getResources().getDrawable(R.drawable.card8));
images.add(getResources().getDrawable(R.drawable.card9));
images.add(getResources().getDrawable(R.drawable.card10));
images.add(getResources().getDrawable(R.drawable.card11));
images.add(getResources().getDrawable(R.drawable.card12));
images.add(getResources().getDrawable(R.drawable.card13));
images.add(getResources().getDrawable(R.drawable.card14));
images.add(getResources().getDrawable(R.drawable.card15));
images.add(getResources().getDrawable(R.drawable.card16));
images.add(getResources().getDrawable(R.drawable.card17));
images.add(getResources().getDrawable(R.drawable.card18));
images.add(getResources().getDrawable(R.drawable.card19));
images.add(getResources().getDrawable(R.drawable.card20));
images.add(getResources().getDrawable(R.drawable.card21));
}
private void loadCards(){
try{
int size = ROW_COUNT*COL_COUNT;
Log.i("loadCards()","size=" + size);
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i=0;i<size;i++){
list.add(new Integer(i));
}
Random r = new Random();
for(int i=size-1;i>=0;i--){
int t=0;
if(i>0){
t = r.nextInt(i);
}
t=list.remove(t).intValue();
cards[i%COL_COUNT][i/COL_COUNT]=t%(size/2);
Log.i("loadCards()", "card["+(i%COL_COUNT)+
"]["+(i/COL_COUNT)+"]=" + cards[i%COL_COUNT][i/COL_COUNT]);
}
}
catch (Exception e) {
Log.e("loadCards()", e+"");
}
}
private TableRow createRow(int y){
TableRow row = new TableRow(context);
row.setHorizontalGravity(Gravity.CENTER);
for (int x = 0; x < COL_COUNT; x++) {
row.addView(createImageButton(x,y));
}
return row;
}
private View createImageButton(int x, int y){
Button button = new Button(context);
button.setBackgroundDrawable(backImage);
button.setId(100*x+y);
button.setOnClickListener(buttonListener);
return button;
}
class ButtonListener implements OnClickListener {
#Override
public void onClick(View v) {
synchronized (lock) {
if(firstCard!=null && seconedCard != null){
return;
}
int id = v.getId();
int x = id/100;
int y = id%100;
turnCard((Button)v,x,y);
}
}
private void turnCard(Button button,int x, int y) {
button.setBackgroundDrawable(images.get(cards[x][y]));
if(firstCard==null){
firstCard = new Card(button,x,y);
}
else{
if(firstCard.x == x && firstCard.y == y){
return; //the user pressed the same card
}
seconedCard = new Card(button,x,y);
turns++;
((TextView)findViewById(R.id.tv1)).setText("Tries: "+turns);
TimerTask tt = new TimerTask() {
#Override
public void run() {
try{
synchronized (lock) {
handler.sendEmptyMessage(0);
}
}
catch (Exception e) {
Log.e("E1", e.getMessage());
}
}
};
Timer t = new Timer(false);
t.schedule(tt, 1300);
}
}
}
class UpdateCardsHandler extends Handler{
#Override
public void handleMessage(Message msg) {
synchronized (lock) {
checkCards();
}
}
public void checkCards(){
if(cards[seconedCard.x][seconedCard.y] == cards[firstCard.x][firstCard.y]){
firstCard.button.setVisibility(View.INVISIBLE);
seconedCard.button.setVisibility(View.INVISIBLE);
}
else {
seconedCard.button.setBackgroundDrawable(backImage);
firstCard.button.setBackgroundDrawable(backImage);
}
firstCard=null;
seconedCard=null;
}
}
}
The easiest way to do this would be to check win conditions with an if statement. This should be done in the method when a turn is actually taken which I assume happens in the turnCard() method.
if (winConditionMet) {
displayWinningScreen();
} else if (lossConditionMet) {
displayLosingScreen();
}
If conditions have been met, then call a method which handles wrapping up that screen, and then launching a new activity. For instance you could add a button to the screen with whatever text you wanted, that when pushed, would take the user to the next screen, be it your score screen, replay screen, main menu, or what have you.
Edit: Okay, since this is a game of memory, you could iterate through the cards at the end of every turn taken and check if any card still has its image set to backImage. If there are none left that are set to backImage, you can then end the game with your code inside of the if statement.
Or, instead of using an ArrayList, you could use some form of Map to keep track of if each card has been permanently turned up or not with the boolean value.

Dynamic background based on a timer (linear layout), how to?

Hi I'm kind of beginner to android OS programming, and I got stuck with a problem, I cant figure out how to do a dynamic background, based on timers (say each 10 seconds a background changes to a different one) I have some code but it comes up with error, here's a sample:
private static final long GET_DATA_INTERVAL = 10000;
int images[] = {R.drawable.smothie1,R.drawable.omletherb1};
int index = 0;
ImageView img;
Handler hand = new Handler();
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
LinearLayout layout= (LinearLayout)findViewById(R.id.LinearView1);
hand.postDelayed(run, GET_DATA_INTERVAL);
}
Runnable run = new Runnable() {
public void run() {
layout.setBackgroundResource(LinearView1).getDrawable(images[index++]);
if (index == images.length)
index = 0;
hand.postDelayed(run, GET_DATA_INTERVAL);
Any help would be greatly apprieciated :D thanks
EDIT: The errors I get are on this line:
layout.setBackgroundResource(LinearView1).getDrawable(images[index++]);
It says that:
-layout cannot be resolved
-the method getDrawable(int) is undefined for the type Object
This error:
layout.setBackgroundResource(LinearView1).getDrawable(images[index++]);
It says that:
-layout cannot be resolved
-the method getDrawable(int) is undefined for the type Object
Please help :)
I have finally worked it out, after removing a few errors I have came up with this (and its working) :
public class CookBookActivity extends Activity {
/** Called when the activity is first created. */
private static final long GET_DATA_INTERVAL = 1000;
int images[] = {R.drawable.omletherb1,R.drawable.smothie1};
int index = 0;
LinearLayout img;
Handler hand = new Handler();
private LinearLayout layout;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
layout = (LinearLayout)findViewById(R.layout.main);
hand.postDelayed(run, GET_DATA_INTERVAL);
Typeface tf2 = Typeface.createFromAsset(getAssets(),
"fonts/BPreplay.otf");
TextView tv2 = (TextView) findViewById(R.id.textView2);
tv2.setTypeface(tf2);
Typeface tf = Typeface.createFromAsset(getAssets(),
"fonts/BPreplay.otf");
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setTypeface(tf);
Button mainNext = (Button) findViewById(R.id.nextScreen1);
mainNext.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent i = new Intent();
i.setClassName("com.unKnown.cookbook", "com.unKnown.cookbook.screen1");
startActivity(i);
}
});
}
Runnable run = new Runnable() {
public void run() {
layout.setBackgroundDrawable(getDrawable(index++));
if (index == images.length)
index = 0;
hand.postDelayed(run, GET_DATA_INTERVAL);
}
};
protected Drawable getDrawable(int i) {
// TODO Auto-generated method stub
return getResources().getDrawable(images[i%2]);
}
}

Regarding android Development

I am doing an application in which I have to display the numbers on TextView randomly and automatically with the help of Timer. I am able to get the random Numbers in the log without repeating, but I am not able to print the same on device please help me...
Regards,
Akki
Source:
//RandomNumber.java
public class RandomNumber extends Activity{
static Random randGen = new Random();
int tambolanum,count=0;
private Button previousbutton;
private Button startbutton;
private Button nextbutton;
int bingonum[]=new int[90];
boolean fill;
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.numbers);
LinearLayout number=(LinearLayout)findViewById(R.id.numbersview);
final TextView randomnum=(TextView)findViewById(R.id.numberstext);
previousbutton=(Button)findViewById(R.id.previous);
nextbutton=(Button)findViewById(R.id.next);
startbutton=(Button)findViewById(R.id.start);
startbutton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Perform action on click
//--- Initialize the array to the ints 0-90
do{
fill = true;
//Get new random number
tambolanum = randGen.nextInt(90) + 1;
//If the number exists in the array already, don't add it again
for(int i = 0; i < bingonum.length; i++)
{
if(bingonum == tambolanum)
{
fill = false;
}
}
//If the number didn't already exist, put it in the array and move
//To the next position
if(fill == true)
{
bingonum[count] = tambolanum;
count++;
}
} while(count < 90);
for(i=0;i
{
randomnum.setText(Integer.toString(bingonum[i]);
}
}
setText(CharSequence text)
The problem you're having is that you're overwriting your text in every itteration of this loop:
for(i=0;i
{
randomnum.setText(Integer.toString(bingonum[i]);
}
You need to build your string first then set it. Something like:
StringBuilder sb = new StringBuilder();
for(i=0;i /* where's the rest of this for-statement? */
{
sb.append(Integer.toString(bingonum[i]);
}
randomnum.setText(sb.toString());

Categories

Resources