8

I'm a java novice and I've using the code below to display a list of clickable TextViews that call a specific class when they are clicked.

It is a list of football team names.

Eg.

Arsenal Manchester United Chelsea

Clicking on TextView Arsenal (TextView id = ars) will call ars.class Clicking on TextView Chelsea (TextView id = che)will call che.class

I have over 20 football team names.

I have an array of textview ids, which I loop through and assign them a clickable action. This works fine.

I have an string array of teamnames, the code loops through the string array and assigns each teamname to a Class object, which is used in the Intent() method.

When I run this code, the list is produced but when I click on a team name it always opens Wol.java, the last position in the string array.

I need some help with the logic, so that when I click on Arsenal it opens ars.class

Here is the code.

public final int[] teams = { R.id.ars, R.id.ast, R.id.bir, R.id.bla,
        R.id.blp, R.id.bol, R.id.che, R.id.eve, R.id.ful, R.id.hul,
        R.id.lee, R.id.liv, R.id.mid, R.id.mnc, R.id.mnu, R.id.nor,
        R.id.nwu, R.id.por, R.id.qpr, R.id.sto, R.id.sun, R.id.swa,
        R.id.tot, R.id.wes, R.id.wig, R.id.wol };

     //String array of teamnames, named to correspond their class name.
public final String[] teamnames = { "ars", "ast", "bir", "bla", "blp",
        "bol", "che", "eve", "ful", "hul", "lee", "liv", "mid", "mnc",
        "mnu", "nor", "nwu", "por", "qpr", "sto", "sun", "swa", "tot",
        "wes", "wig", "wol" };

TextView tv;
Class classname;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.m_transfers);

    setTeamNames(); //Method sets up team names to a Class name.

    for (int i = 0; i < teams.length; i++) {
        tv = (TextView) findViewById(teams[i]);
        tv.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent open = new Intent(Transfers.this, classname);
                startActivity(open);
            }
        });
    }
    ;
}

public void setTeamNames() {
    for (String s : teamnames) {
        String name = "ttj.android.ft.teams." + s;

        try {
            classname = Class.forName(name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    ;
}
tiptopjat
  • 499
  • 3
  • 13
  • 24
  • Are you seriously saying you've created 20 different Activities, one for each team? Why not just have one `Activity` (called `TeamActivity` for example) and pass the team name as a string `Extra` in the `Intent` you use for `startActivity(...)`? – Squonk May 15 '12 at 17:03
  • Very new to android development, still getting my head around the Manifest. Yes, I have created 20 seperate activities in the manifest. Could I make a TeamActivity in the manifest? – tiptopjat May 15 '12 at 17:13
  • @tiptopjat You could make one TeamActivity in the manifest the same way you made the 20 different activities and then, as MisterSquonk said, just add a string or int to the Intent to differentiate. – Tushar May 15 '12 at 17:14
  • Thanks guys, I will give this a go. When you say Intent, are you referring to Intent-filter in the xml file or the Intent method in java? Apologies for the noobie questions! – tiptopjat May 15 '12 at 17:30
  • @tiptopjat: See my answer. No you don't need an `` in the manifest for `TeamActivity` because you create an explicit `Intent` specifying `TeamActivity.class` - no intent filter needed. – Squonk May 15 '12 at 17:34

2 Answers2

5

classname is being overwritten every time you iterate in the foreach loop inside setTeamNames(). Thus, only the last classname remains at the end.

If teams and teamnames have the same number of entries (which they should), you can use the following code and get rid of setTeamNames() completely.

final String prefix = "ttj.android.ft.teams.";
for (int i = 0; i < teams.length; i++) {
    tv = (TextView) findViewById(teams[i]);
    tv.setOnClickListener(new View.OnClickListener() {
       public void onClick(View v) {
       try {
          Class class = Class.forName(prefix + teamnames[i]);               
          Intent open = new Intent(Transfers.this, class);
          startActivity(open);
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        }
    });
}
;
Tushar
  • 8,019
  • 31
  • 38
  • Duh! Thanks Tushar! :-) Only problem I have with this is line 7. Class class = Class.forName(prefix + teamnames[i]); Eclipse says I can not refer to a non-final variable 'i' inside an inner class defined in a different method. – tiptopjat May 15 '12 at 17:03
  • Right, I forgot. You'll either have to set your teamnames and prefix as final or declare them inside the OnClickListener() class. – Tushar May 15 '12 at 17:13
  • Thanks for replying back. 'teamnames' is already Public Final. I've tried declaring teamnames inside the OnClickListener() class. Still no joy. – tiptopjat May 15 '12 at 17:18
  • Did you make String prefix final as well? – Tushar May 15 '12 at 17:23
  • Yes, inside the method Eclipse asked for it to be final. So I moved it outside the method as 'String prefix = "ttj.android.ft.teams.";' The problem still persists. If I made the int in the for loop final, the i++ increment throws an error. – tiptopjat May 15 '12 at 17:29
  • On the first line inside your for-loop, add `final int j = i;` and then replace `teamnames[i]` with `teamnames[j]`. That may be the problem. – Tushar May 15 '12 at 17:42
  • 1
    Absolutely fantastic! Thank you! It works. I've spent 6 hours trying to work this out, should have registered to this site sooner. Thanks again. – tiptopjat May 15 '12 at 17:50
1

Assuming the activities you are trying to start have similar (or the same) layout and functionality but display different data specific to each team, try the following.

Change your onClick(View v) method as follows...

tv.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        Intent open = new Intent(Transfers.this, TeamActivity.class);
        open.putExtra("team", ((TextView)v).getText());
        startActivity(open);
    }
});

Then create a 'generic' Activity...

public class TeamActivity extends Activity {

    String teamName = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set the layout here

        // Get the Intent and team name with the following...
        teamName = getIntent().getStringExtra("team");

        // Do something with teamName

    }
}

Just register the TeamActivity in your manifest and you should be good to go.

Squonk
  • 48,735
  • 19
  • 103
  • 135
  • Thank you for sharing this solution. I imagine the app will be more efficient using this approach? I've invested so much time in my approach I don't have the energy to start from scratch. Lol. – tiptopjat May 15 '12 at 17:54