this is my first app for android, I've been an iPhone dev for 3 years, it's been a change of mindset, and I still find some things odd. First I don't know if this iPhone background might be causing some troubles, but here's what I'm trying to do:
I want to implement an ActionBar with two options working like a TabBar from iOS:
What I want is that when the user selects an action, some Activity will be presented to the user.
Here's what I'm doing so far (which isn't that much):
I'm Using ActionBarSherlock, I have 3 activities: myApp, First and Second
myapp.java only creates the ActionBar elements and loads the activity_first:
package com.example.myApp;
import com.actionbarsherlock.ActionBarSherlock;
import com.actionbarsherlock.view.MenuItem;
import android.os.Bundle;
import com.actionbarsherlock.ActionBarSherlock.OnCreateOptionsMenuListener;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
public class myApp extends SherlockActivity implements OnCreateOptionsMenuListener {
ActionBarSherlock mSherlock = ActionBarSherlock.wrap(this);
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("myApp");
mSherlock.setContentView(R.layout.activity_first);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("First")
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
menu.add("Second")
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}
}
The activities have nothing so far, apart from the generated stub:
import android.app.Activity;
import android.os.Bundle;
public class First extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
}
}
So I have 1 Question and 1 problem:
Question: Is this the correct use of an ActivityBar? I mean, should it be used to switch activities?
Problem: As you can see in the OnCreate method of myApp class, I'm loading the activity_first, It does load the activity, however it loads the ActionBar Twice, like so:
I don't get why is it being loaded twice. If I remove the line: mSherlock.setContentView(R.layout.activity_first); it loads the Bar once, obviously I need to load the activity...
Also I've assigned the NoActionBar theme to the activity_first in the graphical editor of the XML (activity_first.xml), but it doesn't work. What Can I do to load it just once.
Thank you for your valuable time.
Is this the correct use of an ActivityBar? I mean, should it be used to switch activities?
You can think of "First" and "Second" as being the equivalent of toolbar buttons in a desktop app. You are welcome to have those action bar items start up activities if you wish.
As you can see in the OnCreate method of myApp class, I'm loading the activity_first, It does load the activity, however it loads the ActionBar Twice, like so:
Delete this line:
ActionBarSherlock mSherlock = ActionBarSherlock.wrap(this);
and change mSherlock.setContentView(R.layout.activity_first); to just setContentView(R.layout.activity_first);. I believe that will clear up your problems.
Related
I created two simple classes in Android Studio: MainActivity and Activity2.
I created a code in which, when the smartphone is on the MainActivity screen, a user can slide his own finger, that goes from the MainActivity screen to the Activity2 screen.
But how do you tell Android that when a user slides their finger on the screen, the code must pass from the MainActivity screen to the Activity2 screen?
Please, can anyone help me?
The simple codes I wrote:
MainActivity:
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.r0adkll.slidr.Slidr;
import com.r0adkll.slidr.model.SlidrConfig;
import com.r0adkll.slidr.model.SlidrInterface;
import com.r0adkll.slidr.model.SlidrPosition;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SlidrConfig config = new SlidrConfig.Builder().position(SlidrPosition.RIGHT).build();
Slidr.attach(this, config);
}
}
Activity2:
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import com.r0adkll.slidr.Slidr;
import com.r0adkll.slidr.model.SlidrInterface;
public class Activity2 extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
}
}
The Slidr library you are using closes/dismisses the activity by sliding it off.
We usually implement such action in the situation for example, we have ListActivity which displays list of item and DetailsActivity which displays detail of an item. If you click on the list item in ListActivity, we will see it's detail in DetailsActivity. Now, from DetailsActivity, we can slide it off to get back to the ListActivity.
So, there must be one activity in the stack to come back to. I am assuming here, the MainActivity is your parent activity and you are going from MainActivity to Activity2.
in that case you are trying to dismiss the MainActivity to go to Activity2. But, as far as I know, you won't be able to dismiss the host activity with this library. Instead you rather can swipe off Activity2 to get back to MainActivity.
If you want to slide off Activity2 to get back to MainActivity, you can follow along.
Make new style tag in your themes.xml/styles.xml file and add new style for Activity2.
<style name="AppTheme.Actiivty2Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
</style>
You can give any name instead of Actiivty2Theme but make sure AppTheme should be same as your apps main theme/style name. And also do not forget to assign this style for Activity2 in AndroidManifest.xml
Add this line to your root layout of Activity2.
android:background="#color/background_material_light"
Then finally, your sliding code in onCreate() of Activity2
SlidrConfig config = new SlidrConfig.Builder().position(SlidrPosition.RIGHT).build();
Slidr.attach(this, config);
You should now be able to slide off Activity2 to get back to MainActivity.
It seems that a new layout must be created when a new Android activity is created with the wizard in Eclipse. Whenever I create a new Android activity using an existing layout, I have to create a dummy layout, change the layout in onCreate() with setContentView(), then delete the dummy layout.
What is the best way to do this?
Edited Post: If you click File > New > Other, you can choose "Android > Android Activity".
Click next, and fill in the right data. If you reach the "Preview" part, you can select the changes that must be performed. I called the new activity "SecondActivity", which means the layout would file would be called "second_activity.xml". If you uncheck this file in the list, it won't create this file. Then just change your setContentView to the file you want.
You are relying too much on eclipse wizards. Be a programmer. Right click on package add new "class" Give it a name. Extend Activity. Override onCreate methods. In set content view use the layout already created.
Edit: Here are exact instructions
Right click on you package. Click New. Select Class.
Give your class a name, click Ok.
package com.example.fakeapp;
public class FakeActivity {
}
Now extend Activity add in onCreate and onCreateOptionsMenu Use the layout that you need in set content view.
package com.example.fakeapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
public class FakeActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other_activity); //use whatever layout you want.
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Add to the manifest between the tags dont forget to create your title in your res/strings.
<activity
android:name="com.example.fakeapp.Fakeactivity"
android:label="#string/title_activity_fakeactivity" >
</activity>
I did not mean to sound arrogant. What i meant to say was learn what the wizard is doing so you can recreate it and not rely on it to do everything for you. If you are afraid of editing the manifest then that is something that you need to learn.
I have an odd issue which I've never seen anywhere on SO so I've resorted to posting here, hoping I make it clear enough.
I have a simple SherlockFragmentActivity as shown further down which contains three fragments which all call getActivity().setTitle() in their onCreateOptionsMenu() allowing my app to change titles depending on which fragment is visible.
This works as desired, but for some reason (perhaps unrelated) when I exit my application by means of the HOME button occasionally the title isn't visible upon reopening the application. It seems that should I close my app and reopen it, it's fine but after leaving it for a while the title won't be there when I reopen it.
I have absolutely no idea what could be causing this so any help is appreciated. The layout of my application (relevant to this issue) is a basic splash screen (as an activity) with a loading bar which then opens the following FragmentActivity:
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import static java.lang.Math.*;
public class FragmentControl extends SherlockFragmentActivity {
private static final int NUM_PAGES = 3;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_control);
ActionBar action = getSupportActionBar();
action.setDisplayShowTitleEnabled(true);
action.setDisplayShowHomeEnabled(false);
mPager = (ViewPager)findViewById(R.id.pager);
mPagerAdapter = new FragmentControlAdapter(getSupportFragmentManager(), NUM_PAGES);
mPager.setAdapter(mPagerAdapter);
// If this activity wasn't called after a reload
if((Integer)getIntent().getExtras().get("current") == null){
// Always start on the middle page, or as close as possible
mPager.setCurrentItem((int) ceil(NUM_PAGES/2));
// Otherwise start on the page we left for a smoother experience
} else {
mPager.setCurrentItem((Integer)getIntent().getExtras().get("current"));
}
}
}
Only when the application re-opens to the FragmentActivity do I see this issue, when reopening on anything else and navigating to this activity it's fine (as you'd expect).
Any and all help is appreciated, hope I've made it clear.
Oh, and if it matters I'm currently targeting API 17 with minimum support for API 8. The test phone I'm seeing this issue on is a HTC One S - not sure on other devices yet but I'm going to start looking.
occasionally (...) after leaving it for a while
This sounds like your application process is killed in the meantime.
Make sure to save instance state (like what title is displayed) using onSaveInstanceState and restore it in Activity.onCreate or Fragment.onViewCreated.
For instance, the mainActivity.java file is really clustered and to keep it clean i created a second .java(class) where i will execute some code upon a button press. I cannot figure out how to do it at all. And i am not sure what search terms to use either so i apologize if this has been covered.
Heres what i have in my "test" application.
I have a main activity with a single button on it.
package com.test.secondclass;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
Button startButton;
final Intent second = new Intent(getApplicationContext(), testClass.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = (Button)findViewById(R.id.button1);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
startActivity(second);
}
});
}
#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;
}
}
Now here is the "second" class that i made, now remember this is very short i am just using this for an exercise program before implementing it into my actual program.
package com.test.secondclass;
import android.app.Activity;
import android.widget.Toast;
public class testClass extends Activity{
public void onCreate(){
Toast.makeText(getApplicationContext(), "Second class thinger started", Toast.LENGTH_LONG).show();
}
}
And if i try this i get a force close immediately. If i comment out the "intent" part at the very beginning of my main activity then the program runs. But it doesnt do what i want. obviously. Thanks everyone
Add an OnClickListener to send whatever information to testClass, as shown below (untested):
button.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent secondIntent = new Intent();
secondIntent.setClassName(myPackageName, "testClass");
startActivityForResult(secondIntent, REQUEST_CODE);
});
References here and here.
Here's my viewpoint: you are receiving a forced close due the fact that you is trying to open user interface methods (such the Toast) with no context.
IMPORTANT: I'm assuming that you already defined both classes in the manifest.xml file!
Before explaining, I'll make a brief:
Toast: this class opens a quick message, receiving as main arguments the context, the message and the time-to-show;
The context: it is the "environment" where to show. Something like a visual scope, that defines the resources you have. In most cases, you can setup it with setContentView method.
Issue Explanation, in my opinion: The "crash" occurs because you opens the Toast message with no context. An activity is a UI control very similar to a viewpage. If you call a new activity, its very like to call a new page, and so, a new context. In the seccond activity, I haven't see any context. I think that you was assuming that the context is preserved from the first activity, but it ins't because its a new activity.
How to fix:
In the seccond class, define a layout view with setContentView, or...
Reimplement your seccond class as a Service, and call it through startService, or...
Define an AIDL mechams (similar to previous fix, but more sophisticated and complex, as it enables async method calls).
Hope it has helped in some way.
Thank you ALL for the answers!! I was actually able to do what i wanted by using the "stopSelf()" command after i displayed the Toast message. I implemented a service class and when i press the button the testClass.java class gets called and runs the "toast" message then immediately exits by the "stopSelf()" command. I made sure of this by including an "onDestroy()" method which also displayed a simple toast message confirming that the service was stopping :). I usually do stuff like this using threads but it was making the main activity really messy no matter how much formatting i did. So i wanted to have a seperate class i could use.
And to the commenter EfEs, i come from programming in C# language for windows. Android is a new playground for me and im still learning. i think im doing quite well but wasnt sure how to do what i asked. But i figured it out then. And thanks for clearing up that an Activity in android is like a "WindowsForm" in C# where it is completely new GUI for the user. I didnt know that. But thanks to all for helping me with your posts!
I found this on android developers when i was trying to program a button:android developers blog: UI framework changes in Android 1.6
With Android 1.6, none of this is necessary. All you have to do is declare a public method in your Activity to handle the click (the method must have one View argument):
class MyActivity extends Activity { public void myClickHandler(View target){
// Do stuff
}
}
And then reference this method from your XML layout:
<Button android:onClick="myClickHandler" />
can smeone please explain this code to me? I am a beginner in programming, and I don't know what to put in the //do stuff space? I need to reference another activity so i can open another screen. And do i still need to have an activity and put a block of program in the class? this is the code i am using in the class at the moment. Please tell me if i need to update it to use this method:
package com.duncan.hello.world;
import com.duncan.hello.world.R;
import android.app.Activity;
import android.os.Bundle;
public class OtherActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other);
}
}
You put what you want to happen when the button is clicked in the // do stuff part.
You only need to update your code if you're using a button click handler in this fashion.
You might want to start with something a bit simpler, and perhaps not target Android 1.6.