ListView is a widget which shows items in a vertically scrolling list. I figure out a solution to add horizontal scrolling in a ListView. Here is my new object called MyListView, i used OnGestureListener's onScroll methods to manage the horizontal scrolling.
public class MyListView extends LinearLayout implements OnGestureListener { private GestureDetector mGestureDetector; private ListView mListView;
public MyListView(Context context) { super(context); mGestureDetector = new GestureDetector(this); mGestureDetector.setIsLongpressEnabled(false); mListView = new ListView(context); mListView.setItemsCanFocus(true); String[] items = createStrins(); mListView.setAdapter(new ArrayAdapter(context, android.R.layout.simple_list_item_single_choice, items)); this.addView(mListView, new LinearLayout.LayoutParams(350, LayoutParams.FILL_PARENT)); }
@Override public boolean onDown(MotionEvent arg0) { return false; }
iPhone 3G embeds several language setting, it is pretty cool to write an application which has multi language support. Here are 2 solutions we could use to set an UIButton bt's title:
preferredLang returns the default language, it looks like: "en" for English, "fr" for French, "zh-Hans" for Chinese Simp, "zh-Hant" for Chinese Trad etc.
- Set up the text by different language
if ([preferredLang isEqualToString:@"en"]) { [bt setTitle:@"Hello" forState:UIControlStateNormal]; } else if ([preferredLang isEqualToString:@"fr"]) { [bt setTitle:@"Bonjour" forState:UIControlStateNormal]; } ....... else if ([preferredLang isEqualToString:@"zh-Hans"]) { [bt setTitle:@"你好" forState:UIControlStateNormal]; }
Second: - Create a strings file for your project (Add-New File-Strings File), Localizable.strings is a default strings file name, of course you can use the other names
- Make File Localizable: "Get Info" your strings file and click "Make File Localizable" on the left-bottom. You will see "English" shows on the Localizations list, and you can add the other languages by clicking "Add Localization". There are only 4 languages on the default list "English; French, Japnese and German". For the chinese, you should enter "zh_CN" for Chinese Simp and "zh_TW" for Chinese Trad, be careful it is different compare the first solution. After you have done this, there are several files under your strings file.
- Add the keys and values in the languages files. The format is: in English "hello" = "Hello !";
in French "hello" = "Bonjour !"; etc.
Use the same keys for every language and just change the values. The iPhone will detect its language setting to load the right language file.
- Get the right text. If your strings file's name is Localizable, use NSLocalizedString(@"hello", nil) to get the value of "hello", if you use the other name, you should use NSLocalizedStringFromTable(@"hello", @"File name', nil) to return the text.
So the set bt's title, there is only one line of code:
When the orientation of screen changed (portrait to landscape or reciprocate action), the current Activity will be paused->stopped->destroyed and then created->started->resumed with the new configuration (such as language changed, orientation changed..). It means we can detect the orientation on the OnCreate method, to get the current orientation, here is an example:
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { Log.i("info", "landscape"); } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { Log.i("info", "portrait"); }
So you can load the diffrent layout xml file to change your UI or change the layout parameter directly in the code.
As we know the UITableView in the SDK allows to create a vertical scrolling table, but in my project i need a table which has horizontal scrolling. Why don't i create an UIScrollView, because i would like the header of table should be stable.
So what i do is create an UIScrollView which contains an UITableView, and the UIScrollView's contentsize equals the UITableView's size, then the UIScrollView won't do the vertical scrolling stuff.
There is one unconvenient thing when scroll verticaly, you should get the focus on the UITableView first, that means you should press on the screen to select a table cell and then scroll verticaly.
In the UISwitch Class Reference, it said "The UISwitch class is not customizable". But i saw UISwitch's texts are not "ON/OFF" in some apps, in the UISwitch Class Reference doesn't contain such methods to change the defalut text. I just got the solution from iPhone Dev SDK Forum, someone posted these methods:
_UISwitchSlider? what's that? I think you must have the same question? we can't find this class in the official reference documents. You can check by youself, it really exists in the official SDK, using [yourSwitch subviews] could show you that your UISwitch has an array of _UISwitchSlider, and then you can finally find your UISwitch contains 2 UILabel objects, and we can change their values.
I don't know if the future SDK will documentation these stuff, and i'm afraid there definitely has some other "hidden" methods, i can't understand why Apple doing this for developer, if they would like to release a SDK for public, they should release the whole documents.
1. Generate a keystore using JDK's keytool, here is an example: keytool -genkey -alias youraliasname -keyalg RSA -validity 10000 -keystore yourkeystorename
After executer this line, you should type your keystore password, several personal informations, confimation and type another password for your alias.
2. Sign your application (.apk) with jarsigner, here is an example: jarsigner -keystore yourkeystorepath apkpath youraliasname
Type your keystorepwd to start the signing process.
After these steps, you can install your application on the emulator, or on the device? (I didn't try)
${PRODUCT_NAME} presents as its name, it was defined in the info.plist, it is used for "Bundle display name", ''Bundle identifier", "Bundle name", and its default value is the project name. But you can change it using xcodebuild or XCode, how can we get its value in the code, here is an example:
XCode has a very useful toll which named xcodebuild, it allows to compile a XCode project by command line, here is an example:
xcodebuild PRODUCT_NAME="AppName"
the PRODUCT_NAME argument is defined in the info.plist of your project which means the application's name, it is also the name showen in your iPhone or simulator.
The xcodebuild command is executed only in the project directory, so you should use it in the right place.
It's the first time i met this problem on Mac, all my menu bar items disappeared after login. I found a solution to resolve this, delete Users/yourname/Library/Preferences/com.apple.systemuiserver.plist then log out and back in or just a simple restart your Mac.
I'm working on the migration my project from M5 to 0.9, i got some exceptions of SQLite which shows "Table/Cursor has not been deactivated or closed" in my database class, i found the problems come from the Cursor. After read the API documents, i understand each opened Cursor should be deactivated and closed after reading its content. Here is an example:
Cursor cursor = sqlite.query(table, null, selection, null, null, null, null); if (cursor.getCount() > 0){ int cursorCount = cursor.getCount(); ArrayList records = new ArrayList(); cursor.moveToFirst(); for (int i=0; i
CFStringRef textColorKey = CFSTR("defaultTextColor"); CFStringRef colorBLUE = CFSTR("BLUE"); // Set up the preference. CFPreferencesSetAppValue(textColorKey, colorBLUE, kCFPreferencesCurrentApplication); // Write out the preference data. CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
Reading a simple data from preference:
CFStringRef textColorKey = CFSTR("defaultTextColor"); CFStringRef textColor; // Read the preference. textColor = (CFStringRef)CFPreferencesCopyAppValue(textColorKey, kCFPreferencesCurrentApplication); // When finished with value, you must release it // CFRelease(textColor);
To replace the exist key's value, just overwrite the values of key.
I just passed the presentation of my internship in Penbase, this means my student life is over, i finished my education of university, i am going to start the professional life.
3. You should create a .sql file, there are many ways to do it: you can create with you console by taping sqlite3 file.sql or you can create by coding in your project. In my case, i create the database dynamically, so i create the database file in my code, and i will post an example below.
4. Declare 2 variables in your interface file: sqlite3 *database; NSString *dbPath; In you implementation file: - (void) createTable { dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"db.sql"]; if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) { NSString *createSql = @"CREATE TABLE test (text varchar(255))"; if (sqlite3_exec(database, [createSql cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, NULL) == SQLITE_OK) { NSLog(@"create table"); NSString *insertSql = @"INSERT INTO test (text) VALUES('fff')"; int testvalue = sqlite3_exec(database, [insertSql cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, NULL); if (testvalue == SQLITE_OK) { NSLog(@"insert query ok"); } else { NSLog(@"error code %i", testvalue); } } } }
and this method will show you how to use the select query: - (void) findRowNb { NSString *selectSql = @"SELECT COUNT(*) FROM test"; sqlite3_stmt *statement; if (sqlite3_prepare_v2(database, [selectSql cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) { while (sqlite3_step(statement) == SQLITE_ROW) { int count = sqlite3_column_int(statement, 0); NSLog(@"row nb %i", count); } } }
Create an object of NSMutableURLRequest, you can set the header field in this object. And then create an object of NSURLConnection with the parameter of NSMutableURLRequest and delelgate (its self).
The start method "start" is not necessary, in my case i got application crashed when i add start method. Don't forget set up a timer [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]; after the start method.
The last thing is use the delegate methods of NSURLConnection, such as: (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data (void)connectionDidFinishLoading:(NSURLConnection *)connection
In these method, you can check the status of connection, received data and cancel the connectin in connectionDidFinishLoading.
this connection in the main thread, it has a default time to wait for http response and received data. But if we put this connection in a separate thread, it won't wait for response, in this case we should add the follow line to wait the connection response
To create a new thread: [NSThread detachNewThreadSelector:@selector(threadSelector) toTarget:self withObject:nil];
in the threadSelector method we add what we want the thread to do, but don't forget to create a new NSAutoreleasePool object to manage all the autoreleased objects in the thread.
En Objective-C, nous devons avoir le chemin absolue pour lire unfichier, même ce fichier est dans le meme répertoire des fichiers sources. Mais pour une application mobile, cette manipulation ne marche plus, parce que l'appareil mobile ne possède pas de même structure de fichier par rapport les ordinateur.
Une solution pour résoudre ce problème, mettre ce fichier dans la "Resource" de XCode, n'oublie pas cocher la case de le copier. Pour récupérer le chemin vers ce fichier:
I created a object of ListView and my own LinearLayout for each row. The first row contains each column's name, so when i refresh this ListView, the first row don't change, so i pass the first row's value to a variable, and use clear() to remove all my ListView's element, and then add the variable in the ListView. I thought what i should do is create new LinearLayout and add them in ListView, with notifyDataSetChanged() method the ListView should be refreshed.
A problem comes, in the "refreshed" ListView there isn't new values, the values displayed are the first row which contains all column's name and the first row of value which should be deleted by the below clear().
I checked the list in the adapter of ListView, all the new values didn't added in the adapter's list. I can't figure out what is going on here.
The solution i found right now is after clear all the items, create a new adapter like adapter = new MyAdapter(this), and don't forget reset this adapter in the ListView.
Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future. (From java.sun.com)
Vic Gundotra - Engineering VP Allen Hurff, MySpace Steve Horowitz - Android (mobile platform - cool demo) [0:22] Kevin Gibbs - App Engine [0:33] Mark Lucovsky - GData and AJAX API's [0:44] Bruce Johnson - GWT Google Web Toolkit [0.55] David Glazer - Open Social [1:09] Nat Brown, iLike
In a main thread, we could create the child thread to do some work in the same time. But how can we get the return value of a child thread before continue the main thread, we should wait the child thread finish before call the other method.
The solution is join() of Thread, it waits for this thread to die.
ChildThread ct = new ChildThread(); ct.start(); ct.join();
In theandroid-sdk_m5-rc15_windows, the horizontal scroll bar doesn'twork. Thereis a method setHorizontalScrollBarEnabled( Boolean ) in View class, but there is only vertical scroll bar displayed. It might be a bug in this version.
After several researches of CameraDevice class, i found a good exemple to show how it works. I added a start button to launch the camera, press the middle button to save an image, the image is saved in /data/data/name of package/files/. Press the back button to continue take pictures.
public class CameraTest extends Activity{ private Preview mPreview; private int i = 0;
/** Called when the activity is first created. */ @Override public void onCreate(Bundle icicle) { super.onCreate(icicle);
// Make sure to create a TRANSLUCENT window. This is recquired // for SurfaceView to work. Eventually this'll be done by // the system automatically. getWindow().setFormat(PixelFormat.TRANSLUCENT); mPreview = new Preview(this);
LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL);
Button bt = new Button(this); bt.setText("start"); bt.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { setContentView(mPreview); } });
layout.addView(bt, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); setContentView(layout); }
@Override protected boolean isFullscreenOpaque() { // Our main window is set to translucent, but we know that we will // fill it with opaque data. Tell the system that so it can perform // some important optimizations. return true; }
@Override protected void onResume() { // Because the CameraDevice object is not a shared resource, // it's very important to release it when the activity is paused. super.onResume(); mPreview.resume(); }
@Override protected void onPause() { // Start Preview again when we resume. super.onPause(); mPreview.pause(); }
// Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); mHasSurface = false;
// In this example, we hardcode the size of the preview. In a real // application this should be more dynamic. This guarantees that // the uderlying surface will never change size. mHolder.setFixedSize(320, 240); }
public void resume() { // We do the actual acquisition in a separate thread. Create it now. if (mPreviewThread == null) { mPreviewThread = new PreviewThread(); // If we already have a surface, just start the thread now too. if (mHasSurface == true) { mPreviewThread.start(); } } }
public void pause() { // Stop Preview. if (mPreviewThread != null) { mPreviewThread.requestExitAndWait(); mPreviewThread = null; } }
public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, start our main acquisition thread. mHasSurface = true; if (mPreviewThread != null) { mPreviewThread.start(); } }
public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return. Stop the preview. mHasSurface = false; pause(); }
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // Surface size or format has changed. This should not happen in this // example. }
class PreviewThread extends Thread { private boolean mDone;
PreviewThread() { super(); mDone = false; }
@Override public void run() { // We first open the CameraDevice and configure it. CameraDevice camera = CameraDevice.open(); if (camera != null) { CameraDevice.CaptureParams param = new CameraDevice.CaptureParams(); param.type = 1; // preview param.srcWidth = 1280; param.srcHeight = 960; param.leftPixel = 0; param.topPixel = 0; param.outputWidth = 320; param.outputHeight = 240; param.dataFormat = 2; // RGB_565 camera.setCaptureParams(param); }
// This is our main acquisition thread's loop, we go until // asked to quit. SurfaceHolder holder = mHolder; while (!mDone) { // Lock the surface, this returns a Canvas that can // be used to render into. Canvas canvas = holder.lockCanvas();
// Capture directly into the Surface if (camera != null) { camera.capture(canvas); }
// And finally unlock and post the surface. holder.unlockCanvasAndPost(canvas); }
// Make sure to release the CameraDevice if (camera != null) camera.close(); }
public void requestExitAndWait() { // don't call this from PreviewThread thread or it a guaranteed // deadlock! mDone = true; try { join(); } catch (InterruptedException ex) { } } } }
First you should enter to your emulator directory (for exemple: android-sdk_m5-rc15_windows/tools ) by "cmd", enter "adb shell mem_profiler" to display memory using information.