Showing posts with label ImageView. Show all posts
Showing posts with label ImageView. Show all posts

Tuesday, November 26, 2013

Universal Image Loader Tutorial

When using images for an android application. You often encounter a situation where you need to display an image located in a remote server. Since displaying images directly on the views would have considerable impact on the application, we need to cache them first before displaying them. To assist me in this scenarios, I use the Universal Image Loader.

To start using this library, you need to include the universal-image-loader-x.y.z.jar file into your project.

Set the permissions on the application manifest:

1:    <uses-permission android:name="android.permission.INTERNET" />  
2:    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  

Create a subclass of the Application class where you will initialize the image loader configuration:
1:  public class UILDemoApplication extends Application {  
2:       @Override  
3:       public void onCreate() {  
4:            super.onCreate();  
5:            ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())  
6:            .threadPriority(Thread.NORM_PRIORITY - 2)  
7:            .denyCacheImageMultipleSizesInMemory()  
8:            .discCacheFileNameGenerator(new Md5FileNameGenerator())  
9:            .tasksProcessingOrder(QueueProcessingType.LIFO)  
10:            .enableLogging()   
11:            .build();  
12:            ImageLoader.getInstance().init(config);  
13:       }  
14:  }  

Update your application manifest to set the name of the Application tag into UILDemoApplication the class name:
1:  <application  
2:      android:name=".UILDemoApplication"  
3:      android:allowBackup="true"  
4:      android:icon="@drawable/ic_launcher"  
5:      android:label="@string/app_name"  
6:      android:theme="@style/AppTheme" >  

To use the image loader, first get an instance to the image loader class. In my sample application, it is located on the ImageListAdapter that I created:
1:       private Context context;  
2:       private ImageLoader imageLoader;  
3:       public ImageListAdapter(Context context) {  
4:            this.context = context;  
5:            imageLoader = ImageLoader.getInstance();  
6:       }  

For loading images on your image view, you can use check on the sample code below
1:            DisplayImageOptions options = new DisplayImageOptions.Builder()  
2:            .cacheOnDisc()  
3:            .build();  
4:            imageLoader.displayImage(urls[position], vh.imageView, options);  

As you can see from the code above, I specified some options for displaying the image. I enabled caching the image on the disc so that we won't need to download the image everytime we need to display it. It is also possible to display the image without any options by just calling:
1:  imageLoader.displayImage(urls[position], vh.imageView);  

The full source code for this tutorial can be found here.

Thursday, June 13, 2013

Displaying Images Taken from Titanium Mobile showCamera Method

While the api documentation for the Ti.Media.showCamera method does a pretty good job in demonstrating how to call the camera application, it does not show how the use or display the image that was captured by the camera. So after spending some time with it, I was able to come up with this solution to display my image.

First, I created a wrapper that will contain my picture:

1:  var imageWrapper = Ti.UI.createView({  
2:       backgroundColor : 'red',  
3:       width : '300dp',  
4:       height : '385dp',  
5:       top : '65dp'  
6:  });  
7:  win.add(imageWrapper);  

Then, on the success callback of the CameraOptionsType, I created an image view that will contain the image data from the native camera application:

1:  var image = event.media;   
2:  tempImage = Ti.UI.createImageView({  
3:   image : image,  
4:   width : '385dp',  
5:   height : '300dp'  
6:  });  

From what I have observed, the images taken on the android device are not properly oriented (maybe its the same on ios), so I rotate the images before adding them on the wrapper I prepared earlier:

1:  var rotation = Ti.UI.create2DMatrix({ rotate : -270 });  
2:  tempImage.transform = rotation;  
3:  imageWrapper.add(tempImage);  

To test the whole application, get the full source code here

Friday, May 10, 2013

Loading Images from Application Data Directory Vs. Assets Directory on Titanium Mobile Android

While working on lists with images on an application, I noticed something weird: loading images  that I cached (created a copy on the local application directory) sometimes fails and blank views are instead shown on the screen.

At first I thought that the downloader is causing the memory leak since I don't set it to null after downloading the images. However, after setting it null (and the other objects I use for copying the file), nothing changed and still the views become blank after some use. After a lot of searching and trying different ways to load the images, I found out that when I load images from the assets directory, they do not disappear.

So to verify if my observation is correct, I performed a test. I created two separate windows with the same UI layout and objects, but one window is loading from the assets directory and one would load from the application data directory. Here is the comparison of the two views:



The picture on the left is the list loading images from the application data directory and the one on the right loads images from the assets directory. As you can see, some of the images on the left picture disappear after the list is scrolled several times.

In titanium all files under the resources directory are stored in the assets folder. So if the images you need to display will be used for a long time or is a permanent part of the application, I would suggest that you place it in the assets directory. If you need to display cached images, it would be better if you use the WebView just like what I previously did.

Full source code for my test application can be downloaded from here.

Friday, March 22, 2013

Smooth Scrolling List/TableView for Titanium Android

For those who have been using the Titanium TableView UI to render lists, you may have noticed that there is a significant lag on the scroll animation when the number of list items are increased. Most of the time, if there are images on the row, the list becomes choppy and sometimes the application crashes (especially on android).  Since most of the solutions I found only adds minimal improvement on the performance, I just accepted this issue as unresolvable until a titanium sdk update handles this.

However, after using different titanium views for a while, I accidentally discovered a viable alternative to the TableView. After seeing WebViews render lists containing a lot of items with ease, I realized that I can use it as a substitute for my TableViews.

To create a "ListView" type of UI on the WebView, I used the html Table on the code like below: (Please note that I have used Mustache for rendering the data on the html template)

1:  <table border="0" style="width:100%;">  
2:                 {{#table_rows}}  
3:                 <tr onclick="Ti.App.fireEvent('app:handleRowSelect', { index : '{{row_index}}' })">  
4:                      <td>  
5:                           <img src="{{{image_url}}}" style="width:320px; height:240px; position:relative; left:10px; top:5px;"/>  
6:                      </td>  
7:                 </tr>  
8:                 {{/table_rows}}  
9:  </table>   

As you can seen on the code, I just used styles to make the rows look like a list on a TableView.  You can also see that I am firing an event whenever a row is clicked. I'll explain later how it is used.. Here is what the views look like when running on Android tablet:



You can make them look almost exactly the same so the user wouldn't notice that you are indeed using only a WebView instead of a ListView on android.

To simulate the TableView "click" event handler, you must declare an event handler on your application to capture the event fired from your html:

1:  function handleRowSelect(e) {  
2:   alert('You have selected the row with index ' + e.index);  
3:  }  
4:    
5:  Ti.App.addEventListener('app:handleRowSelect', handleRowSelect);  

Whenever the app:handleRowSelect is fired from the HTML, the handleRowSelect function will be called and the event data will be passed as parameters to this function. From the HTML code above, the   Event is fired with an object that contains the index of the row: Ti.App.fireEvent('app:handleRowSelect', { index : '{{row_index}}' }) and from this, you will be able to perform any operation on the data corresponding to the row selected.

You can try and see for yourself the huge performance improvement from using the WebView for large lists on android from here