After having read quite a lot about it I decided to use ActionBarSherlock to provide a modern look and at the same time support older Android versions.
I created an Android tab based application using the Eclipse Project wizard and modyfied it to use ActionBarSherlock. The result of the main activity is like this:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class MainActivity extends SherlockFragmentActivity implements ActionBar.TabListener {
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayHomeAsUpEnabled(false);
// For each of the sections in the app, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText(R.string.title_tab_1).setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_tab_2).setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_tab_3).setTabListener(this));
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
}
The manifest file looks like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.comp.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="android.app.TabActivity" />
</activity>
</application>
</manifest>
When I run it on an Android 4.0.4 device it works fine but when running it on an Android 2.3.3 device it crashes in the "setContentView" line. Any ideas why?
Thanks.
If you want to use ActionBar Sherlock you'll have to use This Theme instead:
Theme.Sherlock.Light
Related
I am implementing action bar with support library in my app. Min api level of my app is 8 and max is 19. In main activity class, I used android.app.ActionBar to import action bar, but it shows following error on getting action bar "Call requires API level 11 (current min is 8): android.app.Activity#getActionBar". So I changed import to 'android.support.v7.app.ActionBar' for action bar, now error changed to this ' cannot convert from android.app.ActionBar to android.support.v7.app.ActionBar'.
My main activity code is as follow.
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
public class MainActivity extends FragmentActivity {
ViewPager Tab;
TabPagerAdapter TabAdapter;
ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabAdapter = new TabPagerAdapter(getSupportFragmentManager());
Tab = (ViewPager)findViewById(R.id.pager);
Tab.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar = getActionBar();
actionBar.setSelectedNavigationItem(position); }
});
Tab.setAdapter(TabAdapter);
actionBar = getActionBar();
//Enable Tabs on Action Bar
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener(){
#Override
public void onTabReselected(android.app.ActionBar.Tab tab,
FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
Tab.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.app.ActionBar.Tab tab,
FragmentTransaction ft) {
// TODO Auto-generated method stub
}};
//Add New Tab
actionBar.addTab(actionBar.newTab().setText("Android").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("iOS").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Windows").setTabListener(tabListener));
}
}
android manifest is
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.learn2crack.tab"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.learn2crack.tab.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
main_activity is
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
windows_frag.xml is
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50sp"/>
</LinearLayout>
One of my fragment is
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class Windows extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View windows = inflater.inflate(R.layout.windows_frag, container, false);
((TextView)windows.findViewById(R.id.textView)).setText("Windows");
return windows;
}}
Kindly help me out. I have also implemented following tutorial but error remain same.
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
Please don't suggest ActionBarSherlock. I want to know my issue before trying other library.
if you are using android.support.v7.app.ActionBar support package, you must use
actionBar = getSupportActionBar();
and change your activity like this
public class MainActivity extends ActionBarActivity
implements ActionBar.TabListener {
// your code goes here
}
How can I get the menu icon to appear on the bottom bar?
It seems too wasteful to have a full bar, empty, just for the menu icon.
My target is Jelly Bean, I am not using Sherlock.
package com.example.test;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
public class MainActivity extends Activity implements ActionBar.TabListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Tab tab = actionBar.newTab().setTabListener(this).setText("TAB LEFT");
actionBar.addTab(tab);
tab = actionBar.newTab().setTabListener(this).setText("TAB RIGHT");
actionBar.addTab(tab);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
}
#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;
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:targetSdkVersion="10" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.test.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
In your AndroidManifest you have to set the targetSdkVersion to 13 or earlier like this:
<uses-sdk android:targetSdkVersion="13" />
The overflow menu then moves to the bottom since Android tries to be version compatible
You can add this entry under the "application" tag in your manifest:
android:uiOptions="splitActionBarWhenNarrow"
read about it here.
I'm trying to make my application start another class.
What im trying to learn is how to get another class to run in the background - like if the user opens the application, the application stays running.
I thought if I could try to open another class by using an intent, it would work. When i run my application on the emulator, it just crashes...
Here is the opening:
package omg.justry;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
//super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
public void onCreate(Bundle savedInstanceState) {
Intent openStartingPoint = new Intent("omg.justtry.PartF**king2");
startActivity(openStartingPoint);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
Here is the "PartF**king2" class:
package omg.justry;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
public class PartF**king2 extends Activity{
public void onCreate(Bundle savedInstanceState) {
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
The thing is, Eclipse doesn't show any errors. I just exported the app and installed it to the emulator using adb.
I also added the class to the AndroidManifest as you see here:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="omg.justry"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="PartF**king2"></activity>
</application>
I think its the manifest now that I look at it but whatever i do, it gets an error or crashes with Eclipse not explaining anything.
In every class, you onCreate(Bundle savedInstanceState) method MUST contain
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
The super is absolutly mandatory, and the setContentView defines the layout for your activity.
And an Activity cannot "run in the background". Start by reading some Android tutorial, and you'll have some clues about what to do.
I set up ABS with a simple Android project and can't find out why no single part of the action bar shows up on 2.3.3 (left), but works perfectly on 4.0 (right: title, tabs and menu).
What I did:
Created new Android Project in Eclipse
Added android:theme="#style/Theme.Sherlock" in <application>
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" />
Changed Java compliance to 1.6 (don't think this matters, should be the default anyway)
Added ABS as library project (compiled against SDK version 15 as well)
Did not add support library to my project (doesn't make a difference if I do)
Note: I have to use static attachment so I cannot extend one of the Sherlock* classes.
Source code:
package de.andidog.testthesherlock;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import com.actionbarsherlock.ActionBarSherlock;
import com.actionbarsherlock.ActionBarSherlock.OnCreateOptionsMenuListener;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
public class TestTheSherlockActivity extends Activity implements ActionBar.TabListener, OnCreateOptionsMenuListener
{
protected ActionBarSherlock sherlock = ActionBarSherlock.wrap(this);
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
sherlock.setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
showTabsNav();
// TODO: check order of these statements
sherlock.setContentView(R.layout.main);
setContentView(R.layout.main);
}
private void showTabsNav()
{
final ActionBar ab = sherlock.getActionBar();
ab.setDisplayUseLogoEnabled(true);
for(int i = 0; i < 5; ++i)
ab.addTab(ab.newTab().setIcon(R.drawable.ic_launcher).setTabListener(this));
ab.setDisplayShowHomeEnabled(true);
ab.setDisplayShowTitleEnabled(true);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
#Override
public boolean onCreateOptionsMenu(android.view.Menu menu)
{
return sherlock.dispatchCreateOptionsMenu(menu);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
menu.add("Refresh").setIcon(android.R.drawable.ic_menu_rotate).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft)
{
Log.d("TestTheSherlockActivity", "TAB RESELECTED");
}
#Override
public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft)
{
Log.d("TestTheSherlockActivity", "TAB CLICKED");
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft)
{
Log.d("TestTheSherlockActivity", "TAB UNSELECTED");
}
}
My AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.andidog.testthesherlock"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/Theme.Sherlock" >
<activity
android:name=".TestTheSherlockActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
How do I get this to work on 2.x?
Remove the second setContentView call, this is overwriting the layout inflated by ABS.
You should only be using the static attachment technique if you require extending from a non-Android base class. Otherwise it's much easier to extend from SherlockActivity (or any of the others).
For my project all my java classes are in one package - com.example.android.bitmapfun - and my manifest is:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.bitmapfun"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:description="#string/app_description"
android:hardwareAccelerated="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="com.example.android.bitmapfun.ImageGridActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.android.bitmapfun.ImageDetailActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.FullScreen" >
</activity>
</application>
</manifest>
and the Activities are:
package com.example.android.bitmapfun;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
public class ImageGridActivity extends FragmentActivity {
private static final String TAG = "ImageGridFragment";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getSupportFragmentManager().findFragmentByTag(TAG) == null) {
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(android.R.id.content, new ImageGridFragment(), TAG);
ft.commit();
}
}
}
ImageDeatilActivity.java:
package com.example.android.bitmapfun;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;
import com.example.android.bitmapfun.R;
import com.example.android.bitmapfun.Images;
import com.example.android.bitmapfun.DiskLruCache;
import com.example.android.bitmapfun.ImageCache;
import com.example.android.bitmapfun.ImageFetcher;
import com.example.android.bitmapfun.ImageResizer;
import com.example.android.bitmapfun.ImageWorker;
import com.example.android.bitmapfun.Utils;
public class ImageDetailActivity extends FragmentActivity implements OnClickListener {
private static final String IMAGE_CACHE_DIR = "images";
public static final String EXTRA_IMAGE = "extra_image";
private ImagePagerAdapter mAdapter;
private ImageResizer mImageWorker;
private ViewPager mPager;
#SuppressLint("NewApi")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_detail_pager);
.....
}
LogCat: here
Why is the LogCat showing the ClassNotFoundException here? I tried but can't clear the error. Please any ideas to overcome this problem.
To use this FragMentActivity class, your application must specify API Level "11" or higher in its manifest and be compiled against a version of the Android library that supports an equal or higher API Level.
For what it is worth, I couldn't get any of the solutions to work when I imported the BitmapFun project into Eclipse. It was because of the ClassNotFoundException. I did notice that the project was missing the libs folder and the support library, but creating the libs folder and dropping the support library into it did not fix the problem. So, I created a new project in Eclipse, transferred the files over from the original imported project, and it worked on the first try. Victory.