about UX design
a good link
http://www.smashingmagazine.com/2011/03/why-user-experience-cannot-be-designed/
DEAR READER
Claire Keane
taylor price
TVSTRANGERTHINGS

Love Begins

izzy's playlists!
2025 on Tumblr: Trends That Defined the Year
Stranger Things
Aqua Utopia|海の底で記憶を紡ぐ

blake kathryn
I'd rather be in outer space 🛸

Andulka
NASA
"I'm Dorothy Gale from Kansas"
d e v o n
PUT YOUR BEARD IN MY MOUTH
$LAYYYTER
Xuebing Du

Origami Around
Alisa U Zemlji Chuda

seen from Malaysia

seen from United States
seen from South Korea
seen from United States

seen from Netherlands
seen from Philippines
seen from United States
seen from United States

seen from Germany
seen from United States

seen from United States

seen from Türkiye
seen from United States

seen from Malaysia
seen from Maldives
seen from United States
seen from United States

seen from Germany
seen from United States
seen from Italy
@bplusg
about UX design
a good link
http://www.smashingmagazine.com/2011/03/why-user-experience-cannot-be-designed/
Learning iOS development - part 9
long press the run button--> choose profile (command + i)-->the instrument launched
instrument
allocation
automation
chaos monkey
documentation:
/*!
*/
“!” means the comments will show in the help documentation of the class.
Doxygen: Doxygen is the de facto standard tool for generating documentation from annotated C++ sources,objective-c, etc.
modal: “a modal window is a graphical control element subordinate to an application's main window which creates a mode where the main window can't be used.”
CI filters
GPS
CILocationManager
edit info.plist:
“Apparently in iOS 8 SDK, requestAlwaysAuthorization (for background location) or requestWhenInUseAuthorization (location only when foreground) call on CLLocationManager is needed before starting location updates.
There also needs to be NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist with a message to be displayed in the prompt. Adding these solved my problem.”
The allow GPS alert should come up if the settings are correct.
google map, apple map, open street map
mapkit and gpskit are two independent framework. They can be used separately. mapkit takes care of UI, gpskit deals with data.
defensive coding habit: for example, check if nil after alloc init
source tree
Learning Android development - part 6&7&8
part 8
Threads
-Main thread: UI thread
-Background threads: non-UI related, network access must be done on a background thread
techniques for background threads
- Runnables and threads
- AsyncTask
MyAsyncTask extends AsyncTask<GenericParam1, GenericParam2, GenericParam3>
where: • GenericParam1: The type of information that is needed to process the task (e.g., URLs to download) • GenericParam2: The type of information that is passed within the task to indicate progress • GenericParam3: The type of information
There are four methods you can override in AsyncTask. You do not need to override all of them; but you will need to override doInBackGround.
• doInBackground
• The doInBackground() is called by AsyncTask on a background thread. It can run as long as it needs to in order to accomplish whatever work needs to be done for this specific task. Note, though, that tasks are meant to be finite – using AsyncTask for an infinite loop is not recommended.
• The doInBackground() method receives as parameters a varargs array of the first of the data types listed above – the data needed to process the task (in background)
• To doInBackground routine must return a value of the third data type listed above (which is the result of the background work).
• doInBackground can use the tasks publishProgress to pass objects of the 2nd type to onProgressUpdate.
• onPostExecute()
onPostExecute() is called from the UI thread after doInBackground() completes. It receives as a parameter the value returned by doInBackground()
• onPreExecute()
onPreExecute is called from the UI threadbefore the background thread executes doInBackGround. This is usually initialize a status bar or do something to indicate to the user that background work is starting.
• onProgressUpdate()
onProgressUpdate is called from the UI thread It receives as a parameter the items (of the 2nd parameter type) published by thedoInBackground method. This is usually used to indicate some kind of status progress to the user.
How to use AsyncTask:
- Create a subclass of AsyncTask, commonly as a private inner class of something that uses the task (e.g., an activity) - Override one or more AsyncTask methods to accomplish the background work, plus whatever work associated with the task that needs to be done on the UI thread (e.g., update progress) - Create an instance of the AsyncTask subclass and call execute() to have it begin doing its work
see example below
Accessing information on the internet
-URL class: The URL is used to make the necessary requests to connect to the HTTP server of the data object, query for information about the object, and download the object.
The android URL class can both parse URL strings into parts and compose URL strings from parts.
The URL getContent() method downloads and returns the content of the resource that is referred to by this URL. By default this returns an InputStream, or null, if the content type of the response is unknown.
InputStream is = (InputStream) new URL(url).getContent();
Going to the Internet requires the android.permission.INTERNET permission.
Add the following code in manifest.xml
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Example of ActivityFragment file, downloading image in the background
The result of the app
using Runnables
/** * A placeholder fragment containing a simple view. */ public class RunnablesActivityFragment extends Fragment { private static final String TAG = "RunnablesActivity"; String myUrl = "http://www.androidcentral.com/sites/androidcentral.com/files/styles/w680h550/public/postimages/9274/android_kitkat.jpg"; public RunnablesActivityFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_runnables, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); Button getImageButton = (Button) getActivity().findViewById(R.id.at_button); getImageButton.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Log.d(TAG, "onClick: " + myUrl); downloadImage(myUrl); } }); } private Drawable loadImageFromWeb(String url) { Drawable downloadedImage = null; try { InputStream is = (InputStream) new URL(url).getContent(); if (is != null) { downloadedImage = Drawable.createFromStream(is, "src name"); } }catch (Exception e) { System.out.println("Exc="+e); } return downloadedImage; } public void downloadImage(final String myUrl) { new Thread(new Runnable() { Drawable result = null; @Override public void run() { try { Log.d(TAG, "downloadImage" + " thread: " + Thread.currentThread().getId()); result = loadImageFromWeb(myUrl); } catch (Exception e ) { e.printStackTrace(); } getActivity().runOnUiThread(new Runnable() { @Override public void run() { Log.d(TAG, "downloadImage" + " runOnUiThread thread: " + Thread.currentThread().getId()); if (result != null) { ImageView imageView = (ImageView)getActivity().findViewById(R.id.at_image); imageView.setImageDrawable(result); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } else { Log.d(TAG, "downloadImage Problem getting image"); } } }); } }).start(); } }
Another example of making the same function is using AsyncTask
public class AsyncTaskActivityFragment extends Fragment { private static final String TAG = " AsyncTaskActivity "; String myUrl = "http://www.androidcentral.com/sites/androidcentral.com/files/styles/w680h550/public/postimages/9274/android_kitkat.jpg"; public AsyncTaskActivityFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_async_task, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); Button getImageButton = (Button) getActivity().findViewById(R.id.at_button); getImageButton.setOnClickListener(new View.OnClickListener () { public void onClick(View arg0) { Log.d(TAG, "onClick: " + myUrl); new DownloadImageTask().execute(myUrl); } }); } private Drawable loadImageFromWeb(String url) { Drawable downloadedImage = null; try { InputStream is = (InputStream) new URL(url).getContent(); if (is != null) { downloadedImage = Drawable.createFromStream(is, "src name"); } }catch (Exception e) { System.out.println("Exc="+e); } return downloadedImage; } private class DownloadImageTask extends AsyncTask<String, Integer, Drawable> { @Override protected void onPreExecute() { // do nothing for this example; but if you had a progressdialog; set it up here } // doInBackground is called on the background thread // Receives the first parameter; in this case an array of strings with 1 item in it // Needs to return something of the 3 parameter type. // No call to publishProgress; but if publishProgress was called, // would pass something of the 2nd parameter @Override protected Drawable doInBackground(String... params) { Log.d(TAG, "PlaceholderFragment : doInBackground entry " + (String) params[0]); Drawable myDrawable = loadImageFromWeb((String) params[0]); return myDrawable; } // onProgressUpdate called on the UI thread // Receives parameters of the 2nd type @Override protected void onProgressUpdate(Integer... progress) { // do nothing for this example } // Called on UI thread after doInBackground completes; // Receives a parameter of the 3rd type @Override protected void onPostExecute(Drawable result) { Log.d(TAG, "PlaceholderFragment : onPostExecute entry"); ImageView imageView = (ImageView)getActivity().findViewById(R.id.at_image); if (result != null) { imageView.setImageDrawable(result); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } else Log.d(TAG, "PlaceholderFragment : result is null"); } } }
-HttpURLConnection client
Decoding information retrieved from internet
-Json and XML
Example of HttpURLConnection and Json
The get ip buttons get ip address, and location info button gets location information.
Final result:
public class GetIpLocationActivityFragment extends Fragment { private static final String TAG = "GetIpLocation"; private static final int QUERY_GET_IP = 1; private static final int QUERY_GET_IP_LOC_INFO = 2; private int caller = 0; private GetNetworkInfoTask niTask = null; Button getIpLocationInfoButton; public GetIpLocationActivityFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_get_ip_location, container, false); } public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); //getIpButton Button getIpButton = (Button) getActivity().findViewById(R.id.get_ip_btn); getIpButton.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { caller = QUERY_GET_IP; String queryBase = "http://www.telize.com/jsonip"; String queryString = Uri.parse(queryBase).buildUpon().toString(); startNetworkInfoTask(queryString); } }); //getIpLocationInfoButton getIpLocationInfoButton = (Button) getActivity().findViewById(R.id.get_loc_info_btn); getIpLocationInfoButton.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { caller = QUERY_GET_IP_LOC_INFO; TextView ipInfoTV = (TextView) getActivity().findViewById(R.id.ip_addr); String ipInfo = ipInfoTV.getText().toString(); if (TextUtils.isEmpty(ipInfo)){ ipInfo = "8.8.8.8"; } String queryBase = "http://www.telize.com/geoip/"; String queryString = Uri.parse(queryBase).buildUpon().appendPath(ipInfo).toString(); startNetworkInfoTask(queryString); } }); } public class GetNetworkInfoTask extends AsyncTask<String, Integer, String> { private static final String TAG = "GetNetworkInfo"; //in intro class, pass in and use context; private Context context = null; GetNetworkInfoTask(Context context) { this.context = context; } @Override protected void onPreExecute() { // do nothing for this example; but if you had a progressdialog; set it up here } @Override protected String doInBackground(String... params) { String networkInfo = getDataFromWeb((String) params[0]); return networkInfo; } @Override protected void onProgressUpdate(Integer... progress) { // do nothing for this example // setProgressPercent(progress[0]); } // Called on UI thread after doInBackground completes; receives a parameter of the 3rd type @Override protected void onPostExecute(String result) { Log.d(TAG, "PlaceholderFragment : onPostExecute entry"); handleResults(result); } private String getDataFromWeb(String queryString) { Log.d(TAG, "getDataFromWeb " + queryString); String sb = null; try { // Open the connection and get the response from the url. Response should be in json URL url = new URL(queryString); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); int response = urlConnection.getResponseCode(); if (response != HttpURLConnection.HTTP_OK) { Log.e(TAG, "getDataFromWeb HttpURLConnection not ok: " + response); } else { Log.d(TAG, "getDataFromWeb HttpURLConnection is ok: " + response); sb = getInputString(urlConnection); Log.d(TAG, sb); urlConnection.disconnect(); } } catch (Exception e) { Log.e(TAG, this.getClass().getSimpleName() + e + " for url: " + queryString); e.printStackTrace(); } return sb; } private String getInputString(HttpURLConnection urlConnection) { // read the input into a string StringBuffer sb = null; BufferedReader in; try { // urlConnection.getInputStream reads the response body. // InputStreamReader is a java class that turns a byte stream into a character stream // BufferedReader is a java class that wraps an existing reader and buffers the input, to minimize // interaction with the underlying reader as most requests are satisfied from accessing the buffer in = new BufferedReader( new InputStreamReader(urlConnection.getInputStream())); sb = new StringBuffer(""); String line = ""; String NL = System.getProperty("line.separator"); while ((line = in.readLine()) != null) { sb.append(line + NL); } in.close(); } catch (IOException e) { Log.d(TAG, ""); e.printStackTrace(); } return sb.toString(); } } public void handleResults(String results) { Log.d(TAG, "handleResults " + results); IpLocationInfo ipLocationInfo = null; if (results != null) { ParseJsonInfo parseJsonInfo = new ParseJsonInfo(); ipLocationInfo = parseJsonInfo.decodeMessage(results); if (caller == QUERY_GET_IP) { displayResultsIP(ipLocationInfo); } else if (caller == QUERY_GET_IP_LOC_INFO) { displayResultsIPLocInfo(ipLocationInfo); } } } // The following assumes your TextView id is ip_addr; modify the following to match whatever id you gave the TextView that holds the ip address. private void displayResultsIP(IpLocationInfo ipLocationInfo){ TextView textView = (TextView)getActivity().findViewById(R.id.ip_addr); textView.setText(ipLocationInfo.getIp()); } private void displayResultsIPLocInfo(IpLocationInfo ipLocationInfo){ TextView textViewCountry = (TextView)getActivity().findViewById(R.id.ip_country); textViewCountry.setText(ipLocationInfo.getCountry()); TextView textViewTZ = (TextView)getActivity().findViewById(R.id.ip_timezone); textViewTZ.setText(ipLocationInfo.getTimezone()); TextView textViewCity = (TextView)getActivity().findViewById(R.id.ip_city); textViewCity.setText(ipLocationInfo.getCity()); TextView textViewRegion = (TextView)getActivity().findViewById(R.id.ip_region); textViewRegion.setText(ipLocationInfo.getRegion()); TextView textViewLatitude = (TextView)getActivity().findViewById(R.id.ip_latitude); textViewLatitude.setText(ipLocationInfo.getLatitude()); TextView textViewLongtitude = (TextView)getActivity().findViewById(R.id.ip_longitude); textViewLongtitude.setText(ipLocationInfo.getLongitude()); } public void startNetworkInfoTask(String queryString) { // Add code to kill any existing asyncTask if the button is pressed multiple times if(niTask != null) { AsyncTask.Status aiStatus = niTask.getStatus(); Log.d(TAG, " startHttpURLTask :doClick: aiTask status is " + aiStatus); if(aiStatus != AsyncTask.Status.FINISHED) { Log.v(TAG, "startHttpURLTask doClick cancel existing task if not done."); niTask.cancel(true); } } // Start the asyncTask niTask = new GetNetworkInfoTask(getActivity()); niTask.execute(queryString); } }
Learning iOS development - part 8
Network programming
two categories:
socket.io
Multipath TCP:
-new for iOS7
-currently only supported for SIRI
-allow multiple TCP routes to be connected to the application layer as a single socket
e.g. allow transition from wifi to LTE without losing data
CocoaAsyncSocket
-open source sockets library
-simplifies sockets programming
Apple sample apps
-simpleNetworkStream
-WiTap
all network calls should be asynchronous
using a delegate or GCD pattern
NSURLProtocol - intercept URL Requests
NSURLSession - background download (iOS7 only)
Reachability
Erica Sadun’s book: “iPhone Developers Cookbook”
web server from device
Learning c# - part 5
Data Binding
Four major components: source object, source property, target object, target property.
Element Data Binding
ElementName is the source Object, Path is the source property
They <Binding> is inside <Image.Width>. So the target object and property is image width.
A simpler syntax is as follows. The two syntax work exactly the same.
Data can flow both ways.
Simple Data Binding
MpaaRatingTextBlock, and bind its Text property to mpaaRating.MpaaRatingId property, using a pretty explicit syntax
If binding fails, there will not be any exception. An system error will show in the output window.
Complex binding
Learning iOS development - part 7
Blocks
“Blocks are a language-level feature added to C, Objective-C and C++, which allow you to create distinct segments of code that can be passed around to methods or functions as if they were values.”
-why using blocks?
NSArray *items=[[NSArray alloc]initWithObjects:@"one",@"two", nil];
for (NSString *item in items) {
}
[items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { //code here }];
NSOperation/NSOperation Queue is the objective-c version of GCD
Grand central dispatch, GCD might be easier.
See the demo file shown in class
AFNetworking
Alcatraz
Learning Android development - part 6
Action Items:
-Action buttons
-Action overflow
Store information (persisting data), many ways to store information
-SavedInstansState: The instance state is gone when the activity is destroyed via the Back key, “Up” key or finish().
write in onSaveInstanceState
Read in the onCreate
Example:
// Key for an item which will be put into the instance state Bundle private final static String KEY_POSITION = "key_position"; // Value that will be saved and restored through the saved instance state. private int mPosition; Saving information in the saveInstanceState public void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putInt(KEY_POSITION, mPosition); } Retrieving information from the sharedInstanceState: @Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); if (savedInstanceState != null){ mPosition = savedInstanceState.getInt(KEY_POSITION, 0); }
-SharedPreferences:
The Android SharedPreferences class provides a general framework that allows you to save and retrieve persistent key-value pairs of primitive data types.
You can use SharedPreferences to save any primitive data: booleans, floats, ints, longs, and strings.
Data is stored between application instances (i.e. permanently)
This data is written to the database on the device and is available each time the app is opened.
Useful for storing application preferences, settings, etc.
write in onDestroy
read in onCreate
Example:
Setting a shared preference private final static String INITIAL_POSITION = "pref_position"; public static int mPosition; SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); Editor ed = sp.edit(); ed.putInt(INITIAL_POSITION, mPosition); ed.apply(); } Retrieving a shared preferences: SharedPreferences mySharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); mPosition = mySharedPreferences.getInt(INITIAL_POSITION, 0);
-Other ways includes application context, local files and databases, cloud storage, etc.
Learning iOS development - part 6
Internet server
webView: webView delegate
-How does it work if there are two web views, and only one delegate?
In the delegate method: using if condition to work with different web views
NSURLConnectionDataDelegate, NSURLConnectionDownloadDelegate, NSURLConnectionDelegate
AWS - most popular
S3-->create bucket-->lowercase works better-->create folders-->upload files (for example, upload a JSON text file and access the link in the app)
very cheap
Rackspace - fast
AFNetworking
JSON
“JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array. An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.”
notification
built-in class to turn JSON into array/dictionaries, vice versa
Xml
complex data
Learning Android development - part 5
Lists are another common widget used in Android development. Lists present multiple line items in a vertical arrangement.
Adapters are used to get the data from a source and create views for each row.The Adapter is the “glue” between the data and the displayed AdapterView.
ArrayAdapter
By default, ArrayAdapter creates a view for each array item by calling toString() on each item and placing the contents in a TextView.
CursorAdapter
SimpleAdapter
customAdapter
AdapterViews
// Instantiate the listView ListView listView = (ListView) getActivity().findViewById(R.id.planetList); // Create an ArrayAdapter // Parameters: // context (the parent context) // The resource id for a layout file containing a TextView // This TextView is used to instantiate Views. (each row in the list is a view) // Android provides some built in layouts, or you can make your own. // Data ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, planets); // set the adapter (eg the data and the format) into the listView listView.setAdapter(adapter);
Planet 6.1 looks like this:
Now that the ListView is set up. It is time to format each row.
Add a colors.xml in the values folder
Then create a new layout resource file in the layout folder
Change Root element to TextView
Edit this layout file. Nothing will show, the file will be used to format the rows at runtime.
Then change ArrayAdapter layout in the java file.
The app will look at this PlanetList 6.2
Auto import in Preference
SimpleAdapter
show more than 1 element in each row:
There are several ways to do this; including writing a customAdapter class. In some cases, using a SimpleAdapter will suffice
SimpleAdapter maps static data to views defined in an XML file. The data backing the list is an ArrayList of Maps. Each entry in the ArrayList corresponds to one row in the list. The Maps contain the data for each row. ou also specify an XML file that defines the views used to display the row, and a mapping from keys in the Map to specific views.
The SimpleAdapter class needs -An Array of Strings that defines the fields of the input data (from) -An Array of ints that defines the ID’s of the widgets in the layout for the row. (to) -An arrayList of Maps that contains the actual data. -XML format for the list
Example:
// Create the arrayList of Maps holding the data private static final String PLANET_NAME = "planet_name"; private static final String PLANET_TYPE = "planet_value"; List<HashMap<String, String>> mPlanetMaps = new ArrayList<HashMap<String, String>>(); mPlanetMaps.add(fillMap("Mercury", type_planet)); mPlanetMaps.add(fillMap("Venus", type_planet));
// Declare the from and to arrays. // from corresponds to the “keys” we used put into the Map // to corresponds to the position in the layout we want to put each key’s value
//Create the “from” array containing the key names //Create the “to” array containing the id’s for the row
String[] from = new String[] { PLANET_NAME, PLANET_TYPE }; int[] to = new int[] { R.id.planet_name_item, R.id.planet_value_item}; mAdapter = new SimpleAdapter( this, mPlanetMaps , R.layout.planet_item, from, to); listView.setAdapter(mAdapter);
private HashMap<String, String> fillMap(String planet, String type){ HashMap<String, String> planetMap = new HashMap<String, String>(); planetMap.put(PLANET_NAME,planet); planetMap.put(PLANET_TYPE, type); return planetMap; }
custom Adapter
The basic steps for making a custom adapter are to -extend ArrayAdapter -create constructor; pass in context, layout file, data -override getView
Learning C# - part 4
create a WPF project
window hold a layout panel
easy way to create a method is: select the name, ctl+period
partial class: compiler can merge two partial classes with the same name into one class
Learning iOS development - part 5
Core animation layer
every view has a layer. Hit Esc key after backgroudColor, the help will show up. It shows what the data type that is wanted
CoreGraphic.framework
COCOS2D: “Cocos2D-ObjC is a framework for building 2D games, demos, and other graphical/interactive applications for iOS, Mac and Android. “
Learning Android development - part 4
Intents : Asynchronous messages; used to specify the activity to start and to pass data between activities
StartActivity: Activity method to start another Activity. Parameter is an intent. -The intent specifies which activity to start; and can contain information (eg can be used to pass data from the 1st activity to the 2nd activity)
StartActivityForResult: Activity method to start another Activity. One parameter is an intent specifying which activity to start. The intent can contain information (eg can be used to pass data from the 1st activity to the 2nd activity). When the second Activity ends, a result code and an intent is passed back to the calling activity. The intent can be used to pass data from the 2nd activity to the 1st activity.
What is manifest?
“It describes the components of the application — the activities, services, broadcast receivers, and content providers that the application is composed of. It names the classes that implement each of the components and publishes their capabilities (for example, which Intent messages they can handle). These declarations let the Android system know what the components are and under what conditions they can be launched.”
Create a new activity in the project
Add hierarchical parent when creating the new activity
Now the new activity structure is set up. Go to fragment file to build UI.
Edit java files
In the first Activity:
public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); Button showDetails = (Button) getActivity(). findViewById(R.id.button); showDetails.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showDetails(); } }); }
private void showDetails() { Intent intent = new Intent(getActivity(), CarDetails.class); startActivity(intent); }
in the destination Activity
Button b = (Button) getActivity().findViewById(R.id.goBack_button); b.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { getActivity().finish(); } });
Add intent extra
define keys in the extra:
public static String MODEL = "model"; public static String MANUFACTURE = "manufacturer"; public static String COLOR = "color"; public static String PRICE = "price";
in the destination java file, getIntent()
Intent intent = getActivity().getIntent(); Bundle bundle = intent.getExtras(); if (bundle != null){ String manufacturer = (String) bundle.get(MANUFACTURE); tvManufacturer.setText(!TextUtils.isEmpty(manufacturer)? manufacturer:"Unknown");
}
in the first Activity, edit showDetails() method
private void showDetails() { Intent intent = new Intent(getActivity(), CarDetails.class); intent.putExtra(CarDetails.PlaceholderFragment.MODEL, "Skoda" ); intent.putExtra(CarDetails.PlaceholderFragment.MANUFACTURE, "Grand Touring" ); intent.putExtra(CarDetails.PlaceholderFragment.COLOR, "Executive Silver" ); intent.putExtra(CarDetails.PlaceholderFragment.PRICE, "16,000" ); intent.putExtra(CarDetails.PlaceholderFragment.TYPE, "Sedan" ); intent.putExtra(CarDetails.PlaceholderFragment.IMAGE, R.drawable.greatcar); startActivity(intent); }
How startActivityForResult() works?
Implicit intents: Android system determines what to call dependent on intent fields.
Implicit intents do not directly specify the Android components which should be called. They specify the action which should be performed and (typically) an URI which should be used for this action.
The android system determines which component to start by matching the Intent against all of the <intent-filter> descriptions in the installed application package.
An intent filter indicates which intent values are matched by the activity. An intent filter can match actions, categories and data.
In the above case, FastEddy matches action:MAIN which means it’s a main entry point for the application and a category LAUNCHER which means it should be displayed in the top-level launcher (eg its displayed in the area of the phone which shows the icons that will start an app)
Many of the activities in your app will not have filters. This means they can only be started by explicit intents.
How to use implicit intents to start an activity?
Learning iOS development - part 3
TableView
style: plain, grouped
A protocol is a list of methods (similar to interface in Java)
e.g. <UITableViewDelegate>
delegate, datasource
datasource type is id
Trick: quick way to get the required methods of the datasource is cmd+click on the <UITableViewDataSource>, and copy the two required methods into the project
NSInteger (64bits) vs int (32bits)
starting using NSInteger instead of int
very basic example of a tableview:
tableview is scrollable
iOS 8 has autolayout
Trick: type in the return type and then type tableview to loop through all tableview methods.
e.g. heightForRowAtIndexPath
Target/action works well with small actions, e.g. button click.
Delegation: works well with complex relationship
Notification: any class in the whole app can send and receive notification. Best for a quick notification.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
concatenation
An easy way is:
NSString *mydescription=[self.name stringByAppendingFormat:@"%f,%f",123.3,123.4];
Learning Android development - part 3
Style
A style is a collection of properties that specify the look and format for a View (for example a TextView). A style can specify properties such as height, padding, font color, font size, background color, and much more. Properties are name/value pairs.
A style is defined in an XML resource that is separate from the XML that specifies the layout.
Theme
A theme is a style applied to an Activity or entire application, rather than an individual View. Note that themes and styles are syntactically equivalent, (e.g. Themes are styles) they just have a different scope.
However, changing the theme in the graphic layout DOES NOT change the theme for your running app. To do this, you will need to add the theme to the manifest for that activity.
in Manifest:
android:theme="@style/AppDarkTheme "
in style.xml:
<style name="AppDarkTheme" parent="AppBaseDarkTheme"> <item name="android:paddingLeft">@dimen/activity_horizontal_margin</item> <item name="android:paddingRight">@dimen/activity_horizontal_margin</item> </style>
Tip:
Always define your own styles and themes and apply them to the UI elements. It makes it much easier to apply a consistent style across your app.
User Interface:
TextFields: getText(), setText() Buttons: setOnClickListener() Spinners: getSelectedItem()
Spinners are a view that provides a way to select one value from a set. The spinner control displays a list of strings called items in a pop-up window
for example:
in string.xml file: add the string array
<string-array name="Games"> <item>Oregon</item> <item>Oregon State</item> <item>Stanford</item> <item>USC</item> <item>UCLA</item> <item>Washington</item> <item>Washington State</item> </string-array>
in fragment file:
game = (Spinner) getActivity(). findViewById(R.id.cal_tickets_game);
In the default state, a spinner shows its currently selected value. Touching the spinner displays a dropdown menu with all other available values The user can select a value from this drop down list.
Variables & Arithmetic operations
Using variables to hold data Convert numeric data: Integer.parseInt Format numeric data: DecimalFormat Permission
Drawable
copy image file and paste it in the Drawable folder in Android Studio
Java file PlacehoderFragment method for the California Football App
public static class PlaceholderFragment extends Fragment {
double costPerTicket=75.00; int numberOfTickets; double totalCost; String gameChoice;
EditText tickets; Spinner game; TextView result; Button cost;
public PlaceholderFragment() { }
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_cal_football_ticket_calc, container, false); return rootView; }
@Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); tickets=(EditText) getActivity(). findViewById(R.id.cal_tickets_number); game = (Spinner) getActivity(). findViewById(R.id.cal_tickets_game); result = ((TextView) getActivity(). findViewById (R.id.cal_ticket_result)); cost = (Button) getActivity(). findViewById(R.id.cal_tickets_cost);
cost.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getTicketCost(); } }); }
private void getTicketCost(){ gameChoice = game.getSelectedItem().toString(); String ticketsNo=tickets.getText().toString(); if (!TextUtils.isEmpty(ticketsNo)){ numberOfTickets =Integer.parseInt(ticketsNo); totalCost= costPerTicket * numberOfTickets; DecimalFormat currency = new DecimalFormat("$###,###.##"); String message = getResources(). getString(R.string.total_cost)+ " " + gameChoice + " " + getResources().getString(R.string.is)+ " " + currency.format(totalCost); result.setText(message); } else { result.setText(getResources().getString(R.string.need_number)); } } }
Learning iOS development - part 2
frame: origin[CGPoint], size(width, height)[CGFloat]
UIButton is a subclass of UIView
main.m calls AppDelegate-->AppDelegate looks for storyboard-->if the storyboard was deleted, go to info.plist and delete the storyboard file setting by clicking the “-” button
In the example in the class, storyboard was deleted. So some codes need to be set up in AppDelegate to make it work.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { CGRect fullWindow = [UIScreen mainScreen].bounds; self.window = [[UIWindow alloc]initWithFrame:fullWindow]; self.viewController = [[ViewController alloc]initWithNibName:nil bundle:nil]; self.viewController.view.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; }
property modifier nonatomic means not thread safe, UIkit is not thread safe. So use nonatomic on UI objects.
Book: Design Patterns
Facade: create a class that filters the useful methods out of a complicated library
Model-View-Controller
Transform
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //transform three types: scale, rotate, transform angle +=.2; CGFloat radians = angle; [UIView setAnimationDuration:1.2]; redView.transform = CGAffineTransformMakeRotation(radians); [UIView commitAnimations]; [UIView beginAnimations:@"" context:nil]; }
Every view has a tag property
in ViewDidLoad, clean it up using Refactor. Wow!
UIVIew
CGRect myFrame = [LayoutHelper frameForRedView]; redView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 120, 200)]; redView.backgroundColor = [UIColor redColor]; redView.clipsToBounds = YES; [self.view addSubview:redView];
blueView.backgroundColor = [UIColor blueColor]; blueView.alpha = 0.7; //by putting the blueView in the redView, blueView will follow all the redView's transformation. //by default the blueView will not be affected by the boundry of redView. Using redView.clipsToBounds=YES to bounds blueView into redView. [redView addSubview:blueView]; UIView *blueView = [[UIView alloc]initWithFrame:[LayoutHelper frameForRedView]];
Creating a “LayoutHelper” class
+(CGRect)frameForRedView { //CGRect is readonly, you cannot make change to is by fullScreen.size=xxx; CGRect fullScreen = [UIScreen mainScreen].bounds; CGRect screenOne = CGRectInset(fullScreen, 20, 20); return screenOne; }
The order of operation matters!
UIImageView
Typical practice is to copy the image when adding an image into the project.
- (void)setupMyImageView { grillImageView=[[UIImageView alloc]initWithFrame:CGRectMake(20, 20, 250, 380)]; grillImageView.image = [UIImage imageNamed:@"Grill.jpg"]; [self.view addSubview:grillImageView]; oneImageView.animationImages = [NSArray arrayWithObjects:[UIImage imageNamed:@"1.jpg"],[UIImage imageNamed:@"2.jpg"],[UIImage imageNamed:@"3.jpg"],nil]; //since we did not initwithframe, it will be at the left cornor. oneImageView.center = CGPointMake(250, 250); [oneImageView setAnimationDuration:0.6]; [oneImageView setAnimationRepeatCount:10]; [oneImageView startAnimating]; oneImageView.transform = CGAffineTransformMakeScale(0.5, 0.5); //[self.view addSubview:oneImageView]; } oneImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1.jpg"]];
UIWebView
-(void)setupMyWebView { webView = [[UIWebView alloc]initWithFrame:[LayoutHelper frameForWebView]]; //index 0 is the very bottom view [self.view insertSubview:webView atIndex:5]; NSURL *url = [NSURL URLWithString:urlString]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [webView loadRequest:request]; } NSString *urlString = @"http://www.alminty.com";
GIMP - knock-off of photoshop
Target-action
Learning Android Development - Part 1&2
Last week Android development online course started. Though it is an online course, which means it is not necessary for me to take any notes, I would love to try making summary of those study material and write them down in the blog. The quoted texts or images would be either from instructors’ pdf or screenshots of the lecture.
Each activity represents a UI Views – UI widgets (Views are classes) ViewGroups – containers hold Views (ViewGroups are classes)
RelativeLayout – container where child views are positioned relative to each other and to the “parent” container LinearLayout - container that aligns all children in a single direction, vertically or horizontally
Activity is a class in the android sdk that is a basic UI component
An important Activity method is onCreate that is called by Android when your activity is started. Typically you override onCreate in your activity so that you can display the activity’s specific UI
The fragment class is used to better modularize the code and help with scaling an application between larger and smaller screens. Fragments are a piece of app UI or behavior that are placed in an activity. Activities can “contain” one or more fragments.
onCreateView is a Fragment method that is called when the fragment is being created. Typically onCreateView is overridden to display the fragment specific UI
Controls
Controls are views that extends from Views.
Alt+Enter to fix imports
Localization:
Toast:
Learning c# II - part 2
To access a class from outside the project:
Two things, one is to add references of the project containing the class, And using xxxxx at the top.
Add existing project to the solution: 2 steps
1) put the project folder into the solution folder
2) in VS, right click solution-->add existing project-->choose the c# file under the solution/project folder
Generics:
Example generic class:
public class Pair<T> { public Pair(T item1, T item2) { Item1 = item1; Item2 = item2; } public T Item2 { get; set; } { T temp = Item1; Item1 = Item2; Item2 = temp; } { return "(" + Item1.ToString() + ", " + Item2.ToString() + ")"; } } public T Item1 { get; set; } public void Swap() public override string ToString()
Example of using the Generic class
var genre1 = new Genre { GenreId = 1, Code = "Dra", Name = "Drama" }; var genre2 = new Genre { GenreId = 2, Code = "Act", Name = "Action" }; Pair<Genre> genrePair = new Pair<Genre>(genre1, genre2); Console.WriteLine("\r\nintPair = " + genrePair); genrePair.Swap(); Console.WriteLine("\r\nAfterSwap = " + genrePair);
int? equals to Nullable<T>
Highlight the key words and hit F1, MSDN documentation will show up.
Compare two ways of filtering, or three ways
Regular way:
Console.WriteLine("\r\nResults:"); var result = FindGenresThatStartWith(dos.Genres, "A"); foreach(Genre g in result) { Console.WriteLine(g); }
private static List<Genre> FindGenresThatStartWith( IEnumerable<Genre> genres, string startString) { var list = new List<Genre>(); foreach (var genre in genres) { if (genre.Name.StartsWith(startString, StringComparison.CurrentCultureIgnoreCase)) list.Add(genre); } return list; }
Generic way:
Console.WriteLine("\r\nResults(Generic):"); var resultg = dos.Genres.Where(GenreNameStartsWithA); foreach (Genre g in resultg) { Console.WriteLine(g); }
public static bool GenreNameStartsWithA(Genre g) { return g.Name.StartsWith("A", StringComparison.CurrentCultureIgnoreCase); }
Lambda expression
A way to write the method that would be used only once into a small chunk in another method directly.
In the following example, Where() to filter by checking if the lamba returns true or false and returns only true results.
Console.WriteLine("\r\nResults(Generic):"); //var resultg = dos.Genres.Where(GenreNameStartsWithA); var resultl = dos.Genres.Where(g => g.Name.StartsWith("A",StringComparison.CurrentCultureIgnoreCase)); foreach (Genre g in resultg) { Console.WriteLine(g); }
Console.WriteLine("\r\nPeople over 40"); var over40 = dos.People.Where(p => p.Age > 40); foreach (var p in over40) { Console.WriteLine(p.FullName + " - " + p.Age); }
OrderBy() to sort
var sort = dos.People.OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
The example above is showing a way to chain the orderby, thenby and whereby together.