I have 3 Tabs
Tab1,Tab2,Tab3
public Class TabLayout extends TabActivity {
Tab1,Tab2,Tab3
}
Each Tab Contains one ListActivity
that means
Tab1>>>Tab1ListActivity(List with Image and Text)
Tab2>>>Tab2ListActivity(List with Image and Text)
Tab3>>>Tab3ListActivity(List with Image and Text)
and if i click on any listitem from(Tab1ListActivity,Tab2ListActivity etc.......)
I'm forwarding to one More Activity(Tab1ListItemActivity,Tab2ListItemActivity etc......)
But My Actual Requirement is if suppose I'm clicking backbutton from Tab2ListItemActivity ,then I
Should be able to forward to Tab2ListActivity
But,if i write my code like this
public class Tab2ListItemActivity extends Activity
{
//on Back Button Pressed
Intent intent=new Intent(Tab2ListItemActivity.this,TabLayout.class);
startActivity(intent);
Tab2ListItemActivity.this.finish();
}
when i execute above code I'm able to forward to my TabLayout(Tab1ListActivity) but not to Tab2ListActivity?,Beacuse
Tab2ListItemActivity related to Tab2ListActivity
Could any one help?
Why not leave the default behaviour (do not override onBackPressed)? It will restore to previous Activity.
Solution 1:
Do not finish the TabLayout Activity. And Leave the default implementation of back button in Tab2ListItemActivity activity.
Solution 2 (the hard, the force way):
Add the intent extra on what tab it should open.
Intent intent = new Intent(Tab2ListItemActivity.this, TabLayout.class);
intent.putExtra(TabLayout.EXTRA_TAB_TO_OPEN, 1);
startActivity(intent);
Tab2ListItemActivity.this.finish();
in TabLayout Activity
#Override
protected void onPostCreate(Bundle state) {
super.onPostCreate(state);
handleTab(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleTab(intent);
}
private void handleTab(Intent intent) {
// init tabs
final int tab = intent.getIntExtra(EXTRA_TAB_TO_OPEN, -1);
if (tab != -1) {
getTabHost().setCurrentTab(tab);
}
}
Why are you trying to override the Back button ? I mean, just let the default behaviour take place and then pressing the back button would take you to the previous activity.
If you really want to do it your way, then you would need to set the tab id before launching the TabLayout activity and inside the onCreate() of TabLayout you would need to check the tab id and launch the corresponding ListActivity. The tab id is 1 by default and that is why it is taking you to the Tab1ListActivity always.
I am getting same issue but i solve using this solution.
TabSample.class
public class TabSample extends TabActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TabHost tabHost = getTabHost();
tabHost.addTab(tabHost.newTabSpec("tab1")
.setIndicator("OPT")
.setContent(new Intent(this, TabGroup1Activity.class)));
tabHost.addTab(tabHost.newTabSpec("tab2")
.setIndicator("EDIT")
.setContent(new Intent(this, TabGroup2Activity.class)));
tabHost.setCurrentTab(1);
}
}
TabGroup1Activity.class
public class TabGroup1Activity extends TabGroupActivity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startChildActivity("OptionsActivity", new Intent(this,OptionsActivity.class));
}
}
OptionsActivity.class
public class OptionsActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.optionspage);
Button back = (Button) findViewById(R.id.BackButton1);
Button next = (Button) findViewById(R.id.NextButton1);
OnTouchListener backListener = new OnTouchListener() {
public boolean onTouch (View v, MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_UP){
finish();
}
return false;
}
};
OnTouchListener nextListener = new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_UP){
Intent edit = new Intent(getParent(), EditActivity.class);
TabGroupActivity parentActivity = (TabGroupActivity)getParent();
parentActivity.startChildActivity("EditActivity", edit);
return true;
}
return false;
}
};
back.setOnTouchListener(backListener);
next.setOnTouchListener(nextListener);
}
}
finally over TabGroupActivity.class which save all the stat instance.
public class TabGroupActivity extends ActivityGroup {
private ArrayList<String> mIdList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mIdList == null) mIdList = new ArrayList<String>();
}
#Override
public void finishFromChild(Activity child) {
LocalActivityManager manager = getLocalActivityManager();
int index = mIdList.size()-1;
if (index < 1) {
finish();
return;
}
manager.destroyActivity(mIdList.get(index), true);
mIdList.remove(index); index--;
String lastId = mIdList.get(index);
Intent lastIntent = manager.getActivity(lastId).getIntent();
Window newWindow = manager.startActivity(lastId, lastIntent);
setContentView(newWindow.getDecorView());
}
public void startChildActivity(String Id, Intent intent) {
Window window = getLocalActivityManager().startActivity(Id,intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
if (window != null) {
mIdList.add(Id);
setContentView(window.getDecorView());
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//preventing default implementation previous to android.os.Build.VERSION_CODES.ECLAIR
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed();
return true;
}
return super.onKeyUp(keyCode, event);
}
public void onBackPressed() {
int length = mIdList.size();
if ( length > 1) {
Activity current = getLocalActivityManager().getActivity(mIdList.get(length-1));
current.finish();
}
}
}
This is awesome solution you can try this.and make appropriate manifest entry.
Related
I have two activities, Main Activity and List Activity. I always want a menu displayed on Main Activity as there's no where else to go.
Main Activity has this code:
#Override
public void onOptionsMenuClosed(Menu menu) {
// Nothing else to do, closing the activity.
finish();
}
#Override
public void onResume() {
super.onResume();
openOptionsMenu();
}
When I close List Activity, my entire app closes - and its due to the onOptionsMenuClosed method in my MainActivity, really confused as to why this is the case, when ListActivity is closed I just want to go back to the menu.
I had the same problem and solved it like this:
public class StartActivity extends Activity{
private boolean cancel = true;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
openOptionsMenu();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.startmenu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.Item1){
cancel = false;
Intent intent = new Intent(this, ActivityA.class);
startActivityForResult(intent, 0);
return true;
}
else if(id == R.id.Item2){
cancel = false;
Intent intent = new Intent(this, ActivityB.class);
startActivityForResult(intent, 0);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0) {
if (resultCode == RESULT_CANCELED) {
openOptionsMenu();
cancel = true;
}
}
}
#Override
public void onOptionsMenuClosed(Menu menu)
{
super.onOptionsMenuClosed(menu);
if(cancel){
finish();
}
}
}
I have an activity that can be asked to run after clicking buttons on many different activities and hence it does not have a "single parent". Therefore in the android manifest I cannot define its parent so I cant get the "Up" button to function properly.
Is there a way I can have the "up" button return to the activity that called it?
You can pass ComponentName of starting activity as an extra
intent = new Intent(this, UpButtonActivity.class);
intent.putExtra(EXTRA_PARENT_COMPONENT_NAME, new ComponentName(this, ThisActivity.class));
startActivity(intent);
The Activity with up button
private ComponentName parent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
parent = getIntent().getParcelable(EXTRA_PARENT_COMPONENT_NAME);
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getId()) {
case android.R.id.home:
if (parent != null) {
final Intent parentIntent = new Intent();
parentIntent.setComponentName(parent);
startActivity(parentIntent);
finish();
return true;
} else {
return super.onMenuItemSelected(featureId, item);
}
//...
}
}
I have a screen with 2 tabs in at the bottom of the screen.
Once I run the app, automatically first tab will be active and the activity related to that screen will be shown (Screen 1). Then when the user clicks on the second tab it opens another activity (Screen 2).
Requirement: I want to show the screen 0 when the app loads instead of showing the screen 1. At this time both the tabs should be inactive(not pressed). Once the user clicks on any tab only the respective screens should open (Screen 1 and screen 2).
How to do it?
The code I used is given below:
public class TabBarActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// Your Tab Titles
String tab_title[] = { "Screen 1", "Screen 2"};
// Your Tab Drawables for their states
int tab_drawables[] = { R.drawable.tab_home_custom,
R.drawable.tab_balance_custom};
// Your Tab Activities
Object tab_act[] = { TabB.class,TabC.class};
// / TabHost setup
final TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
tabHost.setup();
TabSpec tab_spec ;
for (int i = 0; i < tab_act.length; i++) {
tab_spec = tabHost.newTabSpec(tab_title[i]);
tab_spec.setIndicator(tab_title[i],
getResources().getDrawable(tab_drawables[i]));
tab_spec.setContent(new Intent(this, (Class<?>) tab_act[i]));
tabHost.addTab(tab_spec);
}
tabHost.setCurrentTab(0);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
TabBarActivity.this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Just create a new activity, screen 0, and get it to start your tab activity, screen 1 and screen 2, using intents. You can then change you manifest file so that you have your new activity marked as launcher by adding this code to the activity decleration.
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
You will also need to remove that code from your current tab activity.
This is not something the TabActivity would normally support.
You might be able to achieve the desired effect by adding a "dummy" tab:
public class TabBarActivity extends TabActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// Your Tab Titles
String tab_title[] = { "", "Screen 1", "Screen 2"};
// Your Tab Drawables for their states
int tab_drawables[] = { R.drawable.tab_home_custom,
R.drawable.tab_balance_custom};
// Your Tab Activities
Object tab_act[] = {Activity.class, TabB.class,TabC.class};
// / TabHost setup
final TabHost tabHost = (TabHost) findViewById(android.R.id.tabhost);
tabHost.setup();
TabSpec tab_spec ;
for (int i = 0; i < tab_act.length; i++) {
tab_spec = tabHost.newTabSpec(tab_title[i]);
if(i>0) tab_spec.setIndicator(tab_title[i],
getResources().getDrawable(tab_drawables[i]));
tab_spec.setContent(new Intent(this, (Class<?>) tab_act[i]));
tabHost.addTab(tab_spec);
}
tabHost.setCurrentTab(0);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
TabBarActivity.this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
I'm not sure if this will create a blank tab button in the tab bar though
I suppose you want a splash screen with the app logo,you need to create another activity and navigate to the tabActivity from that
public class splash2 extends Activity{
protected boolean _active = true;
protected int _splashTime = 2000;
Intent intent;
Runnable r;
Handler handler;
/** Called when the activity is first created. */
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ( keyCode == KeyEvent.KEYCODE_MENU ) {
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashlayout2);
// startActivity(new Intent(splash2.this,splash1.class));
// thread for displaying the SplashScreen
handler = new Handler();
r=new Runnable() {
public void run() {
intent = new Intent(splash2.this, TabBarActivity .class);
//intent.setClass();
startActivity(intent);
finish();
}
};
handler.postDelayed(r, _splashTime);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
handler.removeCallbacks(r);
intent = new Intent();
intent.setClass(splash2.this, Main_menu.class);
startActivity(intent);
overridePendingTransition( R.anim.slide_in_left2, R.anim.slide_out_left2 );
finish();
}
return true;
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
}
}
and add the following tag to the activity tag of this activity instead of having those tags inside the TabBarActivity
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
It will make this splash screen the default activity
I have a program with 4 different tabs.
One of these tabs is an ActivityGroup which has a ListView in it. When I click on one of the list items, it switches to WebActivity:
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent(TabActivity2.this, WebActivity.class);
Bundle b = new Bundle();
b.putString("URL", URLs[(int)id]);
b.putString("prevActivity", "TabActivity2");
intent.putExtras(b);
replaceContentView("web", intent);
}
});
}
public void replaceContentView(String id, Intent newIntent) {
View view = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .getDecorView(); this.setContentView(view);
}
So now we're in the WebActivity class. Here's the code:
public class WebActivity extends ActivityGroup {
WebView mWebView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web);
Bundle b = getIntent().getExtras();
String URL = b.getString("URL");
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginsEnabled(true);
mWebView.requestFocus();
mWebView.loadUrl(URL);
mWebView.setWebViewClient(new FirstTabWebViewClient());
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
Bundle b = getIntent().getExtras();
String retActivity = b.getString("prevActivity");
if (retActivity == "TabActivity2") {
Intent intent = new Intent(WebActivity.this, TabActivity2.class);
replaceContentView("list_webpages", intent);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void replaceContentView(String id, Intent newIntent) {
View view = getLocalActivityManager().startActivity(id,newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)) .getDecorView(); this.setContentView(view);
}
I had to implement my own onKeyDown because otherwise hitting the Back button resulted in closing the application rather than returning to the ListView.
So the StackOverflowError seems to be a structural problem in my program and I'm not sure how to go about resolving it. Any help would be appreciated.
I ended up using a FrameLayout in the same activity with both WebView and ListView and used visilibity to switch between them.
When I click on a menu item I am presented with the following message in DDMS:
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy#43882778
Here is most of the code from the Main class where the onMenuClick is being ignored.
public class Main extends TabActivity {
public static final int ACTIVITY_CREATE = 0;
private static final int ADD_ID = Menu.FIRST;
private Long listId;
private DbHelper mDbHelper;
private Cursor mCursor;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set the list id
Bundle extras = getIntent().getExtras();
if (extras != null) {
listId = extras.getLong("listId");
}
// Open the database
mDbHelper = new DbHelper(this);
mDbHelper.open();
// Setup the tabs
createTabs();
}
public void createTabs() {
mCursor = mDbHelper.fetchAllCategories(listId);
startManagingCursor(mCursor);
for (int i = 0; i [less than symbol] mCursor.getCount(); i++)
{
createTab(
mCursor.getLong(mCursor.getColumnIndexOrThrow("_id")),
mCursor.getString(mCursor.getColumnIndexOrThrow("category")));
}
}
public void createTab(Long categoryId, String category) {
TabHost tabHost = getTabHost();
TabHost.TabSpec spec;
Intent intent;
intent = new Intent();
intent.putExtra("Test", category);
intent.setClass(this, Categories.class);
spec = tabHost.newTabSpec(category);
spec.setContent(intent);
spec.setIndicator(category);
tabHost.addTab(spec);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0, ADD_ID, 0, R.string.menu_addCategory).setIcon(R.drawable.add_grey);
return true;
}
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case ADD_ID:
addCategory();
return true;
}
return super.onMenuItemSelected(featureId, item);
}
public void addCategory() {
Intent intent = new Intent();
intent.setClass(this, CategoryEdit.class);
startActivityForResult(intent, ACTIVITY_CREATE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
case ACTIVITY_CREATE:
if (resultCode == RESULT_OK) {
Bundle createExtras = intent.getExtras();
mDbHelper.addCategory(createExtras.getString("category"));
}
}
}
}
Originally my CategoryEdit.class wasn't listed in the AndroidManifest.xml file. I have added that to the manifest and still receive the same error.
use ::
public boolean onOptionsItemSelected(MenuItem item) {
instead of::
public boolean onMenuItemSelected(int featureId, MenuItem item) {
Try changing it to intent.setClass(TabActivity.this, CategoryEdit.class);
If that doesn't work I'm gonna need some more output from Logcat, you can one line and it is really helping much.