Understanding and fixing instance handling between classes - android

Im having issues with the app crashing with nullpoint exception.
I know that it crashes when trying to get an ArrayList from pictureTalkFragment. which in this class is only set to PictureTalkFragment ptf;
In other words im trying to get an element (have both getter/setter for the arraylist in ptf, and made the arraylist public as an alternative) from an class and not the instance of that class.
But im just to noob to figure out how to correctly handle getting the instances between classes (activity ---> fragments and back etc). In Java i usually just had an referance in the Constructor that sent the instance/referance with the creation of the new class. But in Android theres all this onCreate (getActivity,getContext ++), Im confused:P When to user where and how:(
the EditPicture was started from this code in GridViewAdapter that extended from PictureTalkFragment (edit in onlongclicklistener)
row.setOnLongClickListener(new View.OnLongClickListener()
{
#Override
public boolean onLongClick(View v) {
PopupMenu popMenu = new PopupMenu(v.getContext(), v);
popMenu.getMenuInflater().inflate(R.menu.picturetalk_popup_menu, popMenu.getMenu());
popMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.edit:
Intent intent = new Intent(getContext(), EditPicture.class);
intent.putExtra("itemUUID", item.getId());
String s = new String("");
context.startActivity(intent);
break;
case R.id.remove:
FileInteraction fileInteraction = new FileInteraction();
fileInteraction.deleteFilesAndFolder(item.getImagePath());
item.setTitle("");
notifyDataSetChanged();
break;
default:
//
}
return true;
}
});
popMenu.show();
return true;
}
});
return row;
EditPicture class
public class EditPicture extends Activity {
private EditText text;
private Button applyBtn;
private ArrayList<PictureItem> piArray;
private PictureItem pi;
private UUID itemID;
private PictureTalkFragment ptf;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
itemID = (UUID) getIntent().getSerializableExtra("itemUUID");
SetLocalArray(ptf.getArray()); //Nullpoint here, and i know why. But not how to get the allready created instance of this class
getPictureItem();
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText) findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button) findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updatePictureItem();
ptf.setArray(piArray);
}
});
}
private void updatePictureItem() {
pi.setTitle(text.toString());
piArray.add(pi);
ptf.setArray(piArray);
}
private void SetLocalArray(ArrayList<PictureItem> array) {
this.piArray = array;
}
private PictureItem getPictureItem() {
pi = new PictureItem("", "");
for (int i = 0; i < piArray.size(); i++) {
if (itemID.equals(piArray.get(i))) {
pi = piArray.get(i);
piArray.remove(i);
}
}
return pi;
}}

I don't know what you are using the array for.
Usually you should not depend on the fragment to get the info, if you want to pass an array of objects to the activity, you should use the Bundle in the activity extras to do so, instead of passing only the UUID, just pass also the array you need.
If you want the lazy option just make a class with a static variable to store the fragment and use it in the activity, which I don't advise.

Related

Refreshing list on RecyclerView

I am fairly new in android programming.
I am having two cases where I am unable to get the list updated.
FIRST
Here is my Activity (QuestionList Activity).
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ques_list);
....
quesList=quesDB.getQues(); //getting arraylist from database
qAdapter = new QuesList_Adaptor(quesList, this, this);
rv_qlist.setAdapter(qAdapter);
qAdapter.notifyDataSetChanged();
}
On other activity, taking user input which updates the database (thus also updates quesList above).
public void save (View view)
{
String ques = et_ques.getText().toString();
String optionA = et_optA.getText().toString();
String optionB = et_optB.getText().toString();
String optionC = et_optC.getText().toString();
String optionD = et_optD.getText().toString();
String ans = et_ans.getText().toString();
QuesDB qd = new QuesDB(this);
boolean b = qd.addQues(ques, optionA, optionB, optionC, optionD, ans);
if (b)
{
Toast.makeText(this, "Question Saved", Toast.LENGTH_SHORT).show();
}
*//so... I have to notify adapter here right? than, what's the way here to reference adaptor and use notifyDataSetChanged*
finish();
SECOND CASE
Setting up Multi-delete on recyclerview. Data is getting deleted but trouble in refreshing the list.
Please take a look into the code, I mentioned there using comments.
On Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
..
StoreNotesDB sdb = new StoreNotesDB(this);
noteslist= sdb.getStoreNotes(); //storing from database to array
mAdapter = new AdaptorNotes(this,noteslist, this);
rv.setAdapter(mAdapter);
}
#Override
public void OnLongClick() {
fab.setVisibility(View.GONE);
inActionMode = true;
actionMode = this.startActionMode(new ContextualCallback());
mAdapter.notifyDataSetChanged();
}
#Override
public void OnClick(AdaptorNotes.MyViewHolder holder, int pos) {
if (holder.chk_notes.isChecked())
{
selected_list.add(noteslist.get(pos));
//counter = counter + 1;
}
else
{
selected_list.remove(noteslist.get(pos));
//counter = counter - 1;
}
}
class ContextualCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
actionMode.getMenuInflater().inflate(R.menu.notescontextual_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
//Toast.makeText(MainActivity.this,"delete",Toast.LENGTH_SHORT).show();
if (selected_list.isEmpty()) {
Toast.makeText(NotesListViewActivity.this, "No item is selected", Toast.LENGTH_SHORT).show();
}
else{
//loop for deleting item from database of the selected list
for (MyStoreNotes myStoreNotes: selected_list)
{
String x = String.valueOf(myStoreNotes.getSl());
int y = storeNotesDB.deleteRow(x);
}
mAdapter.notifyDataSetChanged(); // it doesn't work
inActionMode = false;
selected_list.clear();
Toast.makeText(NotesListViewActivity.this, "Selected List Deleted", Toast.LENGTH_SHORT).show();
actionMode.finish();
}
}
return false;
}......
.....
I'm not sure if you're trying to refresh the data on each load of the activity, or if you are using a different method to refresh your data.
If you want to reload the data each time the recyclerview activity is shown, then you need to call...
quesList.clear();
after declaring the list, and before getting the data. That ensures that you are populating your recyclerview with the latest data from your database.
If this is not what you're asking, please explain what your app is currently doing vs what you want it to do.

Edit an entry in a list view

I'm working on a simple log app that lets the user enter a time and a note, and then displays the entered data in a ListView in a dedicated activity (MainActivty). The time and data are entered in a separate activity (AddTimeActivity) with two EditText's and are passed to MainActivity when tapping the save button through an adapter (TimeTrackerAdapter). Alternatively, a cancel button can be pressed when the user changes their mind. The AddTimeActivity can be accessed through an add button in the action bar default menu. Now I've added a delete button -which is working fine- and an edit button to each row in the list. Now The problem is: How can I add the editing feature without making a new activity dedicated to editing. In Other words, how can I make the AddTimeActivity work with editing and adding in the same time, how can I make my app know that the user tapped the add button and start the AddTimeActivity with empty EditText's, or the user tapped the edit button in one of the rows in the list and passes the the data to be edited to AddTimeActivity and displays them in the EditText's and saves the edited data in the same entry? Sorry for not showing any attempts but I'm actually clueless about the issue.
MainActivity.java
public class MainActivity extends AppCompatActivity {
public TimeTrackerAdapter timeTrackerAdapter;
public int TIME_ENTRY_REQUEST_CODE = 1;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.time_list);
timeTrackerAdapter = new TimeTrackerAdapter();
listView.setAdapter(timeTrackerAdapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
super.onCreateOptionsMenu(menu);
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu_main, menu);
return true;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TIME_ENTRY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String time = bundle.getString("time");
String note = bundle.getString("note");
TimeRecord timeRecord = new TimeRecord(time, note);
timeTrackerAdapter.addTimeRecord(timeRecord);
timeTrackerAdapter.notifyDataSetChanged();
}
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
// noinspection SimplifiableIfStatement
if (id == R.id.add_time_item) {
Intent intent = new Intent(getApplicationContext(), AddTimeActivity.class);
startActivityForResult(intent, TIME_ENTRY_REQUEST_CODE);
return true;
}
else if (id == R.id.about) {
Intent aboutIntent = new Intent(getApplicationContext(), AboutScreen.class);
startActivity(aboutIntent);
}
return super.onOptionsItemSelected(item);
}
}
The AddTimeActivity, onSave and onCancel are the buttons' methods:
public class AddTimeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_time);
}
public void onCancel(View view) {
finish();
}
public void onSave(View view) {
Intent intent = new Intent(AddTimeActivity.this, MainActivity.class);
EditText timeEditText = (EditText) findViewById(R.id.Time_Edit_Text);
String time = timeEditText.getText().toString();
EditText noteEditText = (EditText) findViewById(R.id.Note_Edit_Text);
String note = noteEditText.getText().toString();
intent.putExtra("time", time);
intent.putExtra("note", note);
this.setResult(RESULT_OK, intent);
finish();
}
}
TimeTrackerAdapter.java:
public class TimeTrackerAdapter extends BaseAdapter {
public ArrayList<TimeRecord> times = new ArrayList<TimeRecord>();
#Override
public int getCount() {
return times.size();
}
public TimeTrackerAdapter() {
times.add(new TimeRecord("12:30", "this is the best"));
times.add(new TimeRecord("2:30", "I need this"));
}
#Override
public Object getItem(int position) {
return times.get(position);
}
public void addTimeRecord(TimeRecord timeRecord) {
times.add(timeRecord);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
view = inflater.inflate(R.layout.menu_layout, parent, false);
}
TextView timeView = (TextView) view.findViewById(R.id.time_textView);
TextView noteView = (TextView) view.findViewById(R.id.note_TextView);
Button deleteButton = (Button) view.findViewById(R.id.delete_entry);
deleteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
times.remove(position);
notifyDataSetChanged();
}
});
TimeRecord time = times.get(position);
timeView.setText(time.getTime());
noteView.setText(time.getNote());
return view;
}
}
The question is
How can I add the editing feature without making a new activity dedicated to editing.
or, more generally,
"how do I hand over information to the activity I'm calling ?"
You achieve this by adding extras to the intent which you use to start the activity. For example, in your 'MainActivity' before calling 'startActivityForResult()':
Intent intent = new Intent(this, MyOtherActivity.class);
// in your case, 'extraInformation' could be a boolean (add = yes|no)
intent.putExtra("MyExtraInformationKey", extraInformation);
startActivityForResult(intent,TIME_ENTRY_REQUEST_CODE);
Then in the 'onCreate()' method of the other activity, you question the intent for extras:
Intent i = getIntent();
if (i != null && i.hasExtra(getString("MyExtraInformationKey"))
{
boolean myInfo = i.getBooleanExtra("MyExtraInformationKey");
// proceed as appropriate...
}
For your case of buttons inside ListView rows, you could make the OnClickListener method call another method (like 'doCallMayOtherActivity()') in your 'MainActivity', handing over all relevant information (like the position in the 'times' ArrayList).
This method would then start your add/edit activity, passing the old data out of 'times.get(position)' in a bundle as an extra to the intent.
To access the methods in 'MainActivity' from your adapter class, you could use the following code in 'getView()'
Button editButton=(Button) view.findViewById(R.id.edit_entry);
editButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)parent.getContext()).doCallMyOtherActivity(times.get(position));
}
This way, your other activity could check for the existence of that bundle. If there is none, you have a case of 'add'. Else, you have a case of 'edit'.

Using Intent while saving data of previous Activity

I'm currently trying to guess how do I save a data from a previous Activity.
An example is:
At the startPage.class, I have a few options to choose from(Animation Mode, Image Mode, Text Mode) so if I choose for example Text Mode so the it'll be the RadioButton3 and when I press next it goes to the another Activity. So lets say in that new Activity it has this Intent command. How do I retain the data from the previous activity when I press the backSelection3?
Meaning, when I press the back, I want the RadioButton3 to be the selection still instead of it resetting to the default choice.
backButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent backSelection3 = new Intent(imagemode64by64.this, startPage.class);
startActivity(backSelection3);
}
});
You can use onSaveInstanceState
void onSaveInstanceState(Bundle out) {
String val = ...
out.putString("MYVALUE", val);
super.onSaveInstanceState(val);
}
Then
void onCreate(Bundle savedState) {
if(savedState != null) {
String val = savedState.getString("MYVALUE");
}
}
Or do you mean how to put data for another activity? Then you can do
Intent i = new Intnet(this, OtherActivity.class);
String val = ...
i.putExtra("MYVALUE", val);
startActivity(i);
Then in the other activity
void onCreate(Bundle savedState) {
...
Intent i = getIntent();
String val = i.getStringExtra("MYVALUE");
}
Here is an age old example of passing data between classes:
class A{
static int num = 0;
public void setNum(int number){
num = number
}
}
class B{
public static void main(){
A obja = new A();
obja.setNum(3);
}
}
As soon as you do the operation in class B you can use the num variable in class A.

Android: Create a new intent with a button from a GridView (GridView with Navigation buttons)

I have created a class of type BaseAdapter that is populated with buttons - when you click on a button I want to load a new intent. This has proven difficult on two levels:
You cannot associate the event with the button (one that creates a new intent) inside the Adapter. This is why I send the Buttons as an array to my Adapter (this solution works, but it is messy)
Even though my buttons are created inside the same Activity - they cannot create a new intent from that Activity. The exeption is so great that I have not even gotten a try...catch statement to work.
I have tried reflection, creating the buttons inside the activity and passing them through, passing the context (to call context.startIntent(...))
My question: can someone show me how to create a ButtonAdapter where each button creates a new Intent - even of the same type as the original Activity?
UPDATE: Here is the code because I am getting answers from people who think I am struggling with onClickListeners:
public class ButtonAdapter extends BaseAdapter
{
private Context _context;
private Button[] _button;
public ButtonAdapter(Context c, Button[] buttons)
{
_context = c;
_button = buttons;
}
// Total number of things contained within the adapter
public int getCount()
{
return _button.length;
}
// Require for structure, not really used in my code.
public Object getItem(int position)
{
return _button[position];
}
// Require for structure, not really used in my code. Can
// be used to get the id of an item in the adapter for
// manual control.
public long getItemId(int position)
{
return position;
}
public View getView(int position, View convertView, ViewGroup parent)
{
_button[position].setId(position);
return _button[position];
}
}
---------------
The Activity:
public class MainActivity extends Activity
{
private GridView _gv;
private TextView _heading;
private ButtonAdapter _adapter;
public void LoadActivity(String heading)
{
try
{
Itent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra("Level", "NextPage");
intent.putExtra("Heading", heading);
startActivity(intent);
}
catch (Exception ex)
{
Toast.makeText(getApplicationContext(), String.format("Error LoadActivity: %s", ex.getMessage()), Toast.LENGTH_SHORT).show();
}
}
private void createButtonsAdapter(Button _button[])
{
_buttonadapter = new ButtonAdapter(getApplicationContext(), _button);
_gv.setAdapter(_adapter);
}
private void setupButtons()
{
Button[] _buttons = new Button[2];
String names[] = new String[]{"Button1","Button2"};
for (int i = 0; i < 2; i++)
{
_buttons[i] = new Button(this);
_buttons[i].setText(names[i]);
_buttons[i].setTag(names[i]);
_buttons[i].setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
try
{
LoadActivity(((Button)arg0).getTag().toString());
}
catch(Exception ex)
{
Toast.makeText(getApplicationContext(), String.format("Error button.onClick: %s", ex.getMessage()), Toast.LENGTH_SHORT).show();
}
}
});
}
createButtonsAdapter(_buttons);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
_gv = (GridView)findViewById(R.id.gridview);
_heading = (TextView)findViewById(R.id.tv_heading);
Bundle params = getIntent().getExtras();
if (params == null)
{
setupButtons();
}
else if (params.containsKey("Level"))
{
_heading.setText(params.getString("Heading"));
if (params.getString("Level").equals("NextPage"))
{
//code not here yet
}
else if (params.getString("Level").equals("Chapters"))
{
//future code
}
}
}
}
Excuse the bold and caps but I have had enough silly answers to warrent this:
I HAVE TRIED PUTTING THE ONCLICKLISTENER INSIDE THE GRIDVIEW AND IT DOES NOT WORK EITHER
You cannout load an activity from a class outside that activity, even if you pass the context as a parameter. That is why I have resorted to this method, which completely bombs android, even though I have try catch statements.
Please try give me a solution in the form of a correction to my code, other code, or a tutorial that achieves what I want here. I know how to do a button adapter properly, it is the act of loading an Intent that has forced me to implement it this way.
I suggest the following,
Using a common onClick listner for all the buttons in your grid view
Set tag for all the butons in the getView func. of adapter.
Use the tag Object to decide on the intent to fire from the onClick listener.
I hope it helps..
I guess you can easily manipulate your buttons created in your class extending Base adapter. In the getView method .... if you have button b.. then do it as follows
b.setOnClickListener(new OnClickListener()
{
public void onClick()
{
// Do your stuff here ...
}
});
and if you want to start another activity on Click of this button then you need to pass the calling context to this adapter.
Once again I am answering my own question:
http://bottlecapnet.blogspot.com/2012/01/android-buttons-have-no-place-inside.html
I will just have to style TextViews as I want to see them.

Communication between TabActivity and the embedded activity

I am trying to figure out the best practice of communication between a TabActivity and the child activity embedded in this TabActivity.
In my TabActivity, there is a button. When the button is clicked, I want the child activity embedded in this TabActivity to be updated. I wrote the code like below, and just wonder whether it is a good practice. Thanks.
MyTabActivity.java
public class MyTabActivity extends TabActivity implements OnClickListener {
private TabHost m_tabHost;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ff_tab_activity);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
m_tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
intent = new Intent().setClass(this, ChildActivity.class);
spec = m_tabHost.newTabSpec("Tab 1");
spec.setContent(intent);
tabView = (TextView) inflater.inflate(R.layout.tab_indicator, null);
spec.setIndicator(tabView);
m_tabHost.addTab(spec);
m_tabHost.setCurrentTab(0);
ImageView nextButtonIv = (ImageView) findViewById(R.id.next_button);
nextButtonIv.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.next_button:
synchronized (ChildActivity.class) {
if (null != ChildActivity.s_childActivity) {
ChildActivity.s_childActivity.changeUI();
}
}
break;
}
}
ChildActivity.java
public class ChildActivity extends Activity {
public static ChildActivity s_childActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
synchronized (MatchupsActivity.class) {
s_childActivity = this;
}
setContentView(R.layout.child_activity);
}
public void changeUi() {
code that changes UI
}
protected void onDestroy() {
super.onDestroy();
synchronized (MatchupsActivity.class) {
s_childActivity = null;
}
}
Since TabActivity is an ActivityGroup, I would use one of the following:
getCurrentActivity()
Returns the child tab activity being displayed. In your case, this method will return the instance of ChildActivity being used.
ChildActivity childActivity = (ChildActivity) getCurrentActivity();
getLocalActivityManager().getActivity(String)
Returns the child tab activity given its ID/tab spec name, whatever activity being displayed.
ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
I suggest overriding onNewIntent(Intent) in your ChildActivity:
Intent intent = new Intent();
intent.putExtra("xyz", "whatever"); // or a serializable
ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
childActivity.onNewIntent(intent);
Let me know if it works!
Seems fine. A couple of notes:
- I see no reason for synchronization.
- I'd replace
ChildActivity.s_childActivity.changeUI();
with
if(ChildActivity.s_childActivity != null){
ChildActivity.s_childActivity.changeUI();
}
or even
try{
ChildActivity.s_childActivity.changeUI();
} catch(Exception e){
//log
}
for added paranoid safety. :)
The way above with
ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
childActivity.onNewIntent(intent);
is not very nice. Instead of invoking your activity method directly (it can be null!!!) better do it this way:
Intent intent = new Intent(this, ChildActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(AlbumBrowser.INTENT_EXTRA_FILTER, mediaTitle);
getLocalActivityManager().startActivity("activityIdHere", intent);
Couple of design issues with this, but overall it seems reasonable.
I would forgo the static instance in the ChildActivity class. Why? Well, think about the relationship you're modeling. A TabActivity has a ChildActivity. This is textbook composition, and would be accomplished by adding a ChildActivity field to the TabActivity class, like so:
public class TabActivity {
private ChildActivity child;
//remember to initialize child in onCreate
//then, call methods using child.changeUI();, for example
}
This is better, because A) now I can have multiple instances of TabActivity and ChildActivity that won't interfere with each other (before, it was just a static variable, so only one ChildActivity could be used), and B) the ChildActivity is encapsulated inside the TabActivity class... before, it was a public field, meaning anything can use and modify it (might not be desirable; can often lead to some strange runtime bugs as well as messy, tied-together code) - we changed it to a private field, because we don't really want other classes accessing it in unexpected ways.
The only thing you may need access to from the ChildActivity is the parent (TabActivity). To do this, add the following methods and field to the ChildActivity class, and call the registerParent() method after constructing the ChildActivity:
public class ChildActivity ...{
private TabActivity parent;
public void registerParent(TabActivity newParent){
if (newParent != null){
parent = newParent;
}
}
}
So, if you need access to the parent TabActivity from the child, just call parent.someMethod();
It would also be wise to access fields like parent and child through getters and setters; it might save you some time in the long run.
You can use getParent() to obviate the need to do any of this.
Here's my launcher child class with buttons that switch between activities handled by the tabHost:
public class LaunchPadActivity extends Activity implements OnClickListener {
private static final int ICON_PROFILE = 0;
private static final int ICON_SEARCH = 1;
private static final int ICON_MAP = 2;
private static final int FAVOURITES = 3;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.launchpad);
GridView launchPad = (GridView) findViewById(R.id.launchpad);
launchPad.setAdapter(new LaunchIconAdapter(this));
}
public class LaunchIconAdapter extends BaseAdapter {
private Context mContext;
// references to our images
private Integer[] mThumbIds = { R.drawable.user, R.drawable.find,
R.drawable.map, R.drawable.favourites, R.drawable.reviews,
R.drawable.news, R.drawable.tutorial, R.drawable.info,
R.drawable.options, };
public String[] texts = { "Profile", "Search", "Map", "Favourites",
"Reviews", "News", "Tutorial", "Info", "Options" };
public LaunchIconAdapter(Context c) {
mContext = c;
}
// Number of thumbs determines number of GridView items
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
// Icon elements
LinearLayout launchIcon;
ImageView launchImage;
TextView launchText;
if (convertView == null) {
launchIcon = (LinearLayout) ((LayoutInflater) mContext
.getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.launchicon, null);
} else {
launchIcon = (LinearLayout) convertView;
}
// Add ClickListener with metadata
launchIcon.setTag(new Integer(position));
launchIcon.setOnClickListener(LaunchPadActivity.this);
// Get subviews
launchImage = (ImageView) launchIcon
.findViewById(R.id.launch_image);
launchText = (TextView) launchIcon.findViewById(R.id.launch_text);
// Configure subviews
launchImage.setImageResource(mThumbIds[position]);
launchText.setText(texts[position]);
return launchIcon;
}
}
#Override
public void onClick(View v) {
int position = ((Integer) v.getTag()).intValue();
switch (position) {
case ICON_PROFILE:
Toast.makeText(this, "Profile", Toast.LENGTH_LONG).show();
break;
case ICON_SEARCH:
Toast.makeText(this, "Search", Toast.LENGTH_LONG).show();
((TabActivity) getParent()).getTabHost().setCurrentTab(1);
break;
case ICON_MAP:
Toast.makeText(this, "Map", Toast.LENGTH_LONG).show();
((TabActivity) getParent()).getTabHost().setCurrentTab(2);
break;
case FAVOURITES:
Toast.makeText(this, "Map", Toast.LENGTH_LONG).show();
((TabActivity) getParent()).getTabHost().setCurrentTab(3);
break;
}
}
}
Works like a charm.

Categories

Resources