Dec 8, 2014

Google Play Services 6.5

Google Play services 6.5 includes new features in Google Maps, Google Drive and Google Wallet as well as the recently launched Google Fit API. Also providing developers with more granular control over which Google Play services APIs your app depends on to help you maintain a lean app.

Google Developer content is now available offline


The Google Developer Platform team recently commenced a program to make a subset of the resources available offline to developers who, because of limited or no broadband, had previously been unable to access them. The kits include the latest and greatest content on it such as videos, documentation and SDKs.

Find out more: http://g.co/GDGDevKitPilot


Dec 3, 2014

AdMob Interstitials Best Practices

You can grow your mobile app revenue with high-paying AdMob interstitial ads. Implementing these ads in the right way is better for your users and for you. AdMob poiicies are designed to create a positive user experience, so watch this official video to be sure you're doing it right.

Nov 26, 2014

fplutil - libraries and tools help developing for Android and other platforms

fplutil is a set of small libraries and tools that can be useful when developing applications for Android and other platforms.

Components
  • build_all_android is an all-in-one build script that allows you to build, install and run native (C/C++) Android apps from the command line. This is ideal for build automation, but can also be in a developer’s compile/run loop.
  • buildutil performs the configuration, build and archive steps of Android and Linux C/C++ applications using a suite of Python modules. This suite of modules can automate builds in a continuous integration environment.
  • android_ndk_perf is a desktop tool that enables native (C/C++) developers to measure the CPU utilization of their applications on Android, guiding their optimization efforts.
  • libfplutil enables C/C++ developers to write traditional applications (like Hello World) using "main()" and "printf()" on Android.
Visit: http://google.github.io/fplutil/



Nov 24, 2014

Customize Toast to show longer duration

This example show how to customize Toast to show longer duration, by using CountDownTimer to call toast.show() repeatly. And also show how to make the toast counting.


package com.example.androidtoastduration;

import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.os.Bundle;
import android.os.CountDownTimer;


public class MainActivity extends ActionBarActivity {
 
 Button text1, text2, text3, text4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text1 = (Button)findViewById(R.id.text1);
        text2 = (Button)findViewById(R.id.text2);
        text3 = (Button)findViewById(R.id.text3);
        text4 = (Button)findViewById(R.id.text4);
        
        text1.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    Toast.makeText(
      MainActivity.this, 
      "LENGTH_SHORT", 
      Toast.LENGTH_SHORT).show();
   }});
        
        text2.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    Toast toast = Toast.makeText(
      MainActivity.this, 
      "10 second - Not Work!", 
      Toast.LENGTH_SHORT);
    toast.setDuration(10000); //set duration, not work
    toast.show();
   }});
        
        text3.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    final Toast toast = Toast.makeText(
      MainActivity.this, 
      "10 second", 
      Toast.LENGTH_SHORT);
    toast.show();
    
    new CountDownTimer(10000, 1000)
             {
                 public void onTick(long millisUntilFinished) {
                  toast.show(); 
                 }
                 
                 public void onFinish() {
                  toast.cancel();
                  
                 }
             }.start();
   }});
        
        text4.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    final Toast toast = Toast.makeText(
      MainActivity.this, 
      "10 second", 
      Toast.LENGTH_SHORT);
    toast.show();
    
    new CountDownTimer(10000, 1000)
             {
     int count = 10;
     
                 public void onTick(long millisUntilFinished) {
                  toast.show();
                  count--;
                  toast.setText(count + " sec");
                 }
                 
                 public void onFinish() {
                  toast.cancel();
                  
                 }
             }.start();
   }});
    }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidtoastduration.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    
    <Button
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:textStyle="bold"
        android:text="LENGTH_SHORT" />
    
    <Button
        android:id="@+id/text2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:textStyle="bold"
        android:text="10 sec Toast - NOT Work!" />
    
    <Button
        android:id="@+id/text3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:textStyle="bold"
        android:text="10 sec Toast" />
    
    <Button
        android:id="@+id/text4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40dp"
        android:textStyle="bold"
        android:text="10 sec counting Toast" />

</LinearLayout>

Nov 20, 2014

Introduction to Android Auto


Timothy Jordan Introduces Android Auto. Android Auto brings the Android platform to the car in a way that's optimized for the driving experience. It's the same Google platform you already use for phones, tablets, televisions, watches, and more. In fact, all these experiences will often be in the same APK. But now, your app can also extend to the car in a way that's safer and more efficient for the driver. So drivers can stay connected with their hands on the wheel and their eyes on the road.

Using Android Auto is easy. Users go to the Google Play store and download apps that support Android Auto onto their phone.. When they connect their phone to the car, the phone goes into car mode and casts the Android Auto experience to the car's screen. This means that although all the apps and services are actually running on the phone, they're displayed in the car's dash. Users interact with them using the vehicle's controls such as a built-in touchscreen and microphone.

Oct 29, 2014

Android TV - Using the Leanback library

The LeanBack Support Library makes it easy and fast to build great looking Android TV apps. Ankur Kotwal covers the key components to get you started building apps for Android TV using this library.

DevBytes: Android TV - Using the Leanback library

Oct 9, 2014

Google Play services 6.1

Learn about Google Play services 6.1 in this DevByte from Magnus Hyttsten. Google Play services 6.1 adds Enhanced Ecommerce analytics support from Google Tag Manager and offers new improvements to the Google Drive Android API. With this release, we're also including a refresh of the Google Fit developer preview, so that you can test your fitness apps on any Android device.

Google Play services 6.1

Oct 8, 2014

Html.ImageGetter load image from internet, in AsyncTask

This example code use Html.ImageGetter load image from internet, in AsyncTask, to solve error of android.os.NetworkOnMainThreadException in the old example Html.ImageGetter load image from internet.

package com.example.androidhtmltextview;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import android.support.v7.app.ActionBarActivity;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

 public class HttpGetDrawableTask extends AsyncTask<String, Void, Drawable> {

  TextView taskTextView;
  String taskHtmlString;

  HttpGetDrawableTask(TextView v, String s) {
   taskTextView = v;
   taskHtmlString = s;
  }

  @Override
  protected Drawable doInBackground(String... params) {
   Drawable drawable = null;
   URL sourceURL;
   try {
    sourceURL = new URL(params[0]);
    URLConnection urlConnection = sourceURL.openConnection();
    urlConnection.connect();
    InputStream inputStream = urlConnection.getInputStream();
    BufferedInputStream bufferedInputStream = new BufferedInputStream(
      inputStream);
    Bitmap bm = BitmapFactory.decodeStream(bufferedInputStream);

    // convert Bitmap to Drawable
    drawable = new BitmapDrawable(getResources(), bm);

    drawable.setBounds(0, 0, bm.getWidth(), bm.getHeight());

   } catch (MalformedURLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }

   return drawable;
  }

  @Override
  protected void onPostExecute(Drawable result) {

   final Drawable taskDrawable = result;

   if (taskDrawable != null) {
    taskTextView.setText(Html.fromHtml(taskHtmlString,
     new Html.ImageGetter() {

      @Override
      public Drawable getDrawable(String source) {
       return taskDrawable;
      }
     }, null));
   }

  }

 }

 TextView htmlTextViewRemote;

 String htmlStringRemote = "Image load from internet"
   + "<img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_vBn5OxsMM1fUIK0w8awJdKJjgJJ07cBYdWcCscYMujdoEYWWi549p7J5FYnYJSggLjw2pomiwcseExrMX6X8OarAb-bEQwH-sccJtSyHlGnoUrrVtIbgbXP_60n3nzhAwAA1mMuXoNRf/s400/AndroidHtmlTextView_multi_images.png'>";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  htmlTextViewRemote = new TextView(this);
  setContentView(htmlTextViewRemote);

  htmlTextViewRemote.setText(Html.fromHtml(htmlStringRemote,
   new Html.ImageGetter() {

    @Override
    public Drawable getDrawable(String source) {

     Toast.makeText(getApplicationContext(), source,
       Toast.LENGTH_LONG).show();

     HttpGetDrawableTask httpGetDrawableTask = new HttpGetDrawableTask(
       htmlTextViewRemote, htmlStringRemote);
     httpGetDrawableTask.execute(source);

     return null;
    }

   }, null));

  htmlTextViewRemote.setMovementMethod(LinkMovementMethod.getInstance());

 }

}

In order to load image from internet, permission of "android.permission.INTERNET" have to be added in AndroidManifest.xml.


Sep 22, 2014

Android graphics performance tips


Animations can be used for good or evil. They can either create rich and compelling experiences that help users understand and use the application, or they can demonstrate just how truly awful the performance of your application is as they stutter and jank all over the screen. "Turn it off! Turn it off!" your users will scream. But there's a better way. Graphics performance is at the heart of smooth and seamless animations: optimize your rendering performance and you can turn your users on instead of having them turn you off. 

Chet Haase is the lead of the Android UI Toolkit team, focusing on UI widgets, graphics, performance, animations, and everything else to help make great Android user interfaces. He enjoys taking a break from his real job occasionally to talk about Android at events like this one. His scribblings about Android and less relevant stuff can be found online at google.com/+ChetHaase and @chethaase.

Sep 20, 2014

App Indexing for Google Search



The App Indexing API provides a way for developers to notify Google about deep links in their native apps and allows the Google app, version 3.6 and above, to drive re-engagement through Google Search query autocompletions, providing fast and easy access to inner pages in apps. The deep links reported using the App Indexing API are also used by Google to index app content and are surfaced in Google Search results.

In this video, product manager Lawrence Chang presents an overview of the new App Indexing API for Android that lets you specify links -- through your app itself -- for App Indexing. It also gives you a way to re-engage users through Google Search App autocompletions. We'll provide step-by-step guidelines for how to get started. Take a few minutes and find out how to increase user engagement using the App Indexing API.


Visit: https://developers.google.com/app-indexing/

Sep 12, 2014

Intro To Material Design

These days, UI designers need to be thinking about phones, tablets, laptops, TVs, smartwatches, and beyond. In this DesignByte talk about how Google designers have been working on making cross-platform and multi-screen design easier. We wanted to build a design system that felt at home on every screen, from the smallest watch to the largest TV.

DesignBytes: Intro To Material Design

Sep 10, 2014

ARM Guide to Unity: Enhancing Your Mobile Games

Unity is the most popular game engine on the planet, used to develop games and applications across multiple platforms by over 50% of all developers. The ARM Guide to Unity shows these developers how to get the most out of Unity when developing under the unique challenges of mobile platforms. It includes:
  • Visual quality enhancements for your mobile games and applications
  • Optimizations for both CPU and GPU performance
  • Battery life extension techniques for applications running on ARM® Cortex® CPU and ARM Mali™ GPU-based devices
The ARM Guide to Unity was developed alongside, and based on, an industrial placement student’s experience at ARM.  Joel was tasked with creating a Unity game from scratch on a mobile platform and worked with the internal demo and tools teams to create interesting new effects and ensure the finished application was suitably efficient. The team has collated in this guide all the beneficial hints, tips and techniques which arose over the course of the project which we hope beginner and intermediate developers alike will find useful in future projects.



Download the ARM Guide to Unity, from Mali DEVELOPER CENTER

Aug 27, 2014

Android example using ScheduledExecutorService

java.util.concurrent.ScheduledExecutorService is an ExecutorService that can schedule commands to run after a given delay, or to execute periodically. This example show how to create a one-shot action using ScheduledExecutorService.



package com.example.androidscheduledexecutorservice;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
 
 Button buttonStart;
 
 ScheduledExecutorService scheduledExecutorService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        buttonStart = (Button)findViewById(R.id.start);
        buttonStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    
    Toast.makeText(MainActivity.this, 
      "Start", 
      Toast.LENGTH_LONG).show();
    
    scheduledExecutorService = Executors.newScheduledThreadPool(1);
    
    scheduledExecutorService.schedule(new Runnable(){

     @Override
     public void run() {
      MainActivity.this.runOnUiThread(new Runnable(){

       @Override
       public void run() {
        Toast.makeText(MainActivity.this, 
          "Times-up", 
          Toast.LENGTH_LONG).show();
       }});
      
     }}, 
     5, 
     TimeUnit.SECONDS);
    
   }
   
        });
    }

}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidcountdownprogressbar.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start" />

</LinearLayout>

Aug 25, 2014

android.widget.TextClock example

android.widget.TextClock, Added in API level 17, display the current date and/or time as a formatted string.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidcountdownprogressbar.MainActivity" >
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
 
    <TextClock
        android:id="@+id/clock"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textStyle="bold"
        android:textSize="50sp" />
    
</LinearLayout>

Aug 23, 2014

Android example to execute threads with ExecutorService

ExecutorService is an Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks. This example implement 5 threads to update ProgressBars in background thread. The threads executed by a ExecutorService, with thread pool of 2. Such that only 2 thread is running at any time.


package com.example.androidcountdownprogressbar;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class MainActivity extends ActionBarActivity {
 
 Button buttonStart;
 ProgressBar progressBar1, progressBar2,
  progressBar3, progressBar4, progressBar5;
 
 CountThread countThread1, countThread2,
  countThread3, countThread4, countThread5;
 
 ExecutorService executorService = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        buttonStart = (Button)findViewById(R.id.start);
        progressBar1 = (ProgressBar)findViewById(R.id.progressbar1);
        progressBar2 = (ProgressBar)findViewById(R.id.progressbar2);
        progressBar3 = (ProgressBar)findViewById(R.id.progressbar3);
        progressBar4 = (ProgressBar)findViewById(R.id.progressbar4);
        progressBar5 = (ProgressBar)findViewById(R.id.progressbar5);

        buttonStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    countThread1 = new CountThread(progressBar1);
    countThread2 = new CountThread(progressBar2);
    countThread3 = new CountThread(progressBar3);
    countThread4 = new CountThread(progressBar4);
    countThread5 = new CountThread(progressBar5);
    
    executorService = Executors.newFixedThreadPool(2);
    executorService.execute(countThread1);
    executorService.execute(countThread2);
    executorService.execute(countThread3);
    executorService.execute(countThread4);
    executorService.execute(countThread5);
   }});
        
    }
    
    public class CountThread extends Thread{
     
     ProgressBar progressBar;
     final int MAX_PROGRESS = 10;
     int progress;
     
     CountThread(ProgressBar progressBar){
      this.progressBar = progressBar;
      progress = MAX_PROGRESS;
     }

  @Override
  public void run() {
   
   for(int i=0; i<MAX_PROGRESS; i++){
    progress--;
    MainActivity.this.runOnUiThread(new Runnable(){

     @Override
     public void run() {
      progressBar.setProgress(progress);
     }});
    
    try {
     Thread.sleep(1000);
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   
  }
    }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidcountdownprogressbar.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />

    <ProgressBar
        android:id="@+id/progressbar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar2"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar3"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar4"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    <ProgressBar
        android:id="@+id/progressbar5"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="0" />
    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start" />

</LinearLayout>

Aug 16, 2014

CountDownTimer and ProgressBar

Example of using CountDownTimer to update ProgressBar.


package com.example.androidcountdownprogressbar;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
 
 Button buttonStart;
 ProgressBar progressBar;
 TextView textCounter;
 
 MyCountDownTimer myCountDownTimer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        buttonStart = (Button)findViewById(R.id.start);
        progressBar = (ProgressBar)findViewById(R.id.progressbar);
        textCounter = (TextView)findViewById(R.id.counter);
        
        buttonStart.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    progressBar.setProgress(100);
    myCountDownTimer =  new MyCountDownTimer(10000, 500);
    myCountDownTimer.start();
   }});
        
    }
    
    public class MyCountDownTimer extends CountDownTimer {

  public MyCountDownTimer(long millisInFuture, long countDownInterval) {
   super(millisInFuture, countDownInterval);
  }

  @Override
  public void onTick(long millisUntilFinished) {
   textCounter.setText(String.valueOf(millisUntilFinished));
   int progress = (int) (millisUntilFinished/100);
   progressBar.setProgress(progress);
  }

  @Override
  public void onFinish() {
   textCounter.setText("Finished");
   progressBar.setProgress(0);
  }
     
    }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidcountdownprogressbar.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />

    <ProgressBar
        android:id="@+id/progressbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="100" />
    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Start" />
    <TextView
        android:id="@+id/counter"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textStyle="bold"
        android:textSize="50sp"
        android:gravity="center" />

</LinearLayout>

Aug 15, 2014

Android L for game development

Check out what's new for games in the upcoming Android L release. Learn about new features in the OpenGL graphics and OpenSL Audio APIs and get a small taste of the new Google Play Game Services released after Google I/O.

Aug 13, 2014

Mobile Developer's Guide To The Galaxy, 14th Edition

Mobile Developer's Guide To The Galaxy

The free, community driven handbook about mobile technologies: Over 20 experts from all over the world are sharing their know-how on topics like mobile app design, platform-specific aspects of app development, cross-platform development, mobile analytics, accessibility, monetization, app stores, LBS, NFC, app testing and a lot more.

The book is popular among developers wanting to deepen their knowledge and decision-makers planning to enter the mobile business alike. The content gets updates and extended continuously, 13 editions have been published since 2009 and 50,000 hardcopies have been distributed.



Aug 9, 2014

Samsung Developers Conference Nov 11-13th

Samsung Developers Conference will be hold on Moscone West, San Francisco, November 11-13th, 2014. Signup to be notified: http://samsungdevcon.com/


Aug 7, 2014

Port iOS or Android apps to Windows and Windows Phone

Are you interested in porting your iOS or Android apps to Windows and Windows Phone? Moving to a new platform needn't be as difficult as you think, as this video will demonstrate. Learn about your different options, and the exciting tools available to help you. See you in the Windows app Store!


Check http://channel9.msdn.com/Blogs/One-Dev-Minute/Porting-your-app if you can't view the video here.

Aug 5, 2014

Display formatted date/time using String.format()

Examples of using String.format() to display formatted calendar:


package com.example.androidtime;

import java.util.Calendar;

import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.os.Bundle;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView cal = (TextView)findViewById(R.id.cal);
        
        Calendar calendar = Calendar.getInstance(); 

        cal.setText(
         String.format("%td-%tm-%tY\n", calendar, calendar, calendar) +
         String.format("%ty/%tm/%td\n", calendar, calendar, calendar) +
         String.format("%tI:%tM:%tS %tp\n", calendar, calendar, calendar, calendar) +
         "\n" +
         String.format("%tD\n", calendar) +
         String.format("%tc\n", calendar) +
         String.format("%tF\n", calendar) +
         String.format("%tr\n", calendar)
        );

    }

}

The layout file is same as last post.

Aug 4, 2014

Display date/time in various format with SimpleDateFormat

Examples of using java.text.SimpleDateFormat:


package com.example.androidtime;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.os.Bundle;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView cal = (TextView)findViewById(R.id.cal);
        
        Calendar calendar = Calendar.getInstance(); 
        SimpleDateFormat format1 = new SimpleDateFormat("dd-MM-yyyy");
        SimpleDateFormat format2 = new SimpleDateFormat("yy/MM/dd");
        SimpleDateFormat format3 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        SimpleDateFormat format4 = new SimpleDateFormat("yyyy MMM dd (EEE)");
        SimpleDateFormat format5 = new SimpleDateFormat("hh:mm a");
        SimpleDateFormat format6 = new SimpleDateFormat("HH:mm");

        cal.setText(
         format1.format(calendar.getTime()) + "\n" +
         format2.format(calendar.getTime()) + "\n" +
         format3.format(calendar.getTime()) + "\n" +
         format4.format(calendar.getTime()) + "\n" +
         format5.format(calendar.getTime()) + "\n" +
         format6.format(calendar.getTime())
         );

    }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidtime.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    <TextView
        android:id="@+id/cal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textSize="20sp" />

</LinearLayout>

Related: Display formatted date/time using String.format().

Get time of system

Example to get time (in millisecond and nanosecond) from System, and get instance of Calendar to get current time.


package com.example.androidtime;

import java.util.Calendar;

import android.support.v7.app.ActionBarActivity;
import android.widget.TextView;
import android.os.Bundle;


public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        TextView tim = (TextView)findViewById(R.id.tim);
        TextView cal = (TextView)findViewById(R.id.cal);
        
        tim.setText(
         "currentTimeMillis: " + System.currentTimeMillis() + "\n" +
         "nanoTime" + System.nanoTime() + "\n"
         );
        
        Calendar calendar = Calendar.getInstance(); 
        cal.setText(
         "YEAR: " + calendar.get(Calendar.YEAR) + "\n" +
         "MONTH: " + calendar.get(Calendar.MONTH) + "\n" +
         "DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH) + "\n" +
         "HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY) + "\n" +
         "MINUTE: " + calendar.get(Calendar.MINUTE) + "\n" +
         "SECOND: " + calendar.get(Calendar.SECOND) + "\n"
         );

    }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidtime.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    <TextView
        android:id="@+id/tim"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/cal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

Jul 29, 2014

Android L Developer Preview - Camera2 API

Ankur Kotwal presents the Camera2 API in Android L, which is designed as a very flexible and unified pipeline for all camera related tasks. This API gives you direct control of the camera subsystem including autofocus, asynchronous burst captures and special effects.

Jul 24, 2014

Building Advanced UIs for Android Wear

How to write apps for Android Wear devices that need to support complex interactions with the user. This video will describe the navigational concepts that Wear apps should support in order to integrate well with the device and provide guidance on designing the UI flow of your app. Will also introduce a new UI widget library that allows app authors to create experiences with the same polish and consistency as the system UI. Using this library, app authors will be able to create "stream-like" UIs that provide the same physics and transition animations as the built-in "home" stream or search results stream.

In detail: This talk is meant to be largely around how to use GridViewPager in order to create "stream-like" experiences in apps for Android Wear.

Building Advanced UIs for Android Wear

Jul 15, 2014

Google I/O 2014 Highlights



Relive the best moments of Google I/O 2014, including the keynote, sessions, Developer Sandbox, and After Hours. The keynote and all I/O 2014 sessions are available at: google.com/io

Jul 1, 2014

Google shows L, the latest flavor of Android

At Google I/O in San Francisco, the company previews new design and new user interface features for Android. Dubbed "L", the mobile OS will give users a new look and feel, enhanced notifications, and better performance.

Jun 26, 2014

What's new in Android


Google I/O 2014 - What's new in Android

What's new in Android development tools


Google I/O 2014 - What's new in Android development tools

Official Moto 360 Demo at Google I/O

Meet Moto 360, a classic timepiece powered by Android Wear. Get a sneak peek at just some of the functionalities of Moto 360 in demo we are giving at this year's Google I/O.

Jun 22, 2014

Implement BroadcastReceiver to monitor Bluetooth state changed

Last example show how to Enable Bluetooth using Intent of BluetoothAdapter.ACTION_REQUEST_ENABLE. In this example, we implement a new class BTStateChangedBroadcastReceiver, extends BroadcastReceiver, to monitor Bluetooth state changed.


BTStateChangedBroadcastReceiver.java
package com.example.androidbluetooth;

import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class BTStateChangedBroadcastReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 
    -1);
  
  switch(state){
  case BluetoothAdapter.STATE_CONNECTED:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_CONNECTED", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_CONNECTING:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_CONNECTING", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_DISCONNECTED:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_DISCONNECTED", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_DISCONNECTING:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_DISCONNECTING", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_OFF:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_OFF", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_ON:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_ON", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_TURNING_OFF:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_TURNING_OFF", 
    Toast.LENGTH_SHORT).show();
   break;
  case BluetoothAdapter.STATE_TURNING_ON:
   Toast.makeText(context, 
    "BTStateChangedBroadcastReceiver: STATE_TURNING_ON", 
    Toast.LENGTH_SHORT).show();
   break; 
  }
 }

}

Call registerReceiver(...) to register new BTStateChangedBroadcastReceiver(), to the intent of BluetoothAdapter.ACTION_STATE_CHANGED.
package com.example.androidbluetooth;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 TextView textInfo;
 Button buttonEnableBT;
 BluetoothAdapter bluetoothAdapter;
 
 final static int REQUEST_ENABLE_BT = 1;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  textInfo = (TextView)findViewById(R.id.info);
  buttonEnableBT = (Button)findViewById(R.id.enablebt);
  
  bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  if (bluetoothAdapter == null) {
   textInfo.setText("BlueTooth not supported in this device");
   buttonEnableBT.setEnabled(false);
  }else{
   if (bluetoothAdapter.isEnabled()) {
    buttonEnableBT.setEnabled(false);
    textInfo.setText("BlueTooth enabled");
   }else{
    buttonEnableBT.setEnabled(true);
    textInfo.setText("BlueTooth disabled, click button to turn on BlueTooth.");
   }
   
   //register BroadcastReceiver
   registerReceiver(new BTStateChangedBroadcastReceiver(), 
    new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
  }
  
  buttonEnableBT.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
       startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
   }});

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  
  if(requestCode == REQUEST_ENABLE_BT){
   if(resultCode==RESULT_OK){
    Toast.makeText(MainActivity.this, "BlueTooth Turned On", Toast.LENGTH_LONG).show();
   }else{
    Toast.makeText(MainActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
   }
  }
  
  if (bluetoothAdapter.isEnabled()) {
   buttonEnableBT.setEnabled(false);
   textInfo.setText("BlueTooth enabled");
  }else{
   buttonEnableBT.setEnabled(true);
   textInfo.setText("BlueTooth disabled, click button to turn on BlueTooth.");
  }
  
 }

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidbluetooth.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    <TextView
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/enablebt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Enable BlueTooth" />

</LinearLayout>

Permission of "android.permission.BLUETOOTH" is needed in AndroidManifest.xml.
<uses-permission android:name="android.permission.BLUETOOTH"/>


Jun 18, 2014

Check BlueTooth status, and enable it using Intent of BluetoothAdapter.ACTION_REQUEST_ENABLE

This example check if Bluetooth supported in running device and its ON/OFF status. Then call startActivityForResult() with Intent of BluetoothAdapter.ACTION_REQUEST_ENABLE, when user click button to enable it. Then re-check the status again in onActivityResult() when result returned.


MainActivity.java
package com.example.androidbluetooth;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 TextView textInfo;
 Button buttonEnableBT;
 BluetoothAdapter bluetoothAdapter;
 
 final static int REQUEST_ENABLE_BT = 1;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  textInfo = (TextView)findViewById(R.id.info);
  buttonEnableBT = (Button)findViewById(R.id.enablebt);
  
  bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  if (bluetoothAdapter == null) {
   textInfo.setText("BlueTooth not supported in this device");
   buttonEnableBT.setEnabled(false);
  }else{
   if (bluetoothAdapter.isEnabled()) {
    buttonEnableBT.setEnabled(false);
    textInfo.setText("BlueTooth enabled");
   }else{
    buttonEnableBT.setEnabled(true);
    textInfo.setText("BlueTooth disabled, click button to turn on BlueTooth.");
   }
   
  }
  
  buttonEnableBT.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
       startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
   }});

 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  
  if(requestCode == REQUEST_ENABLE_BT){
   if(resultCode==RESULT_OK){
    Toast.makeText(MainActivity.this, "BlueTooth Turned On", Toast.LENGTH_LONG).show();
   }else{
    Toast.makeText(MainActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
   }
  }
  
  if (bluetoothAdapter.isEnabled()) {
   buttonEnableBT.setEnabled(false);
   textInfo.setText("BlueTooth enabled");
  }else{
   buttonEnableBT.setEnabled(true);
   textInfo.setText("BlueTooth disabled, click button to turn on BlueTooth.");
  }
  
 }

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidbluetooth.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    <TextView
        android:id="@+id/info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/enablebt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Enable BlueTooth" />

</LinearLayout>

Add <uses-permission android:name="android.permission.BLUETOOTH"/> in AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidbluetooth"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.BLUETOOTH"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.androidbluetooth.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>

May 19, 2014

Save something in SharedPreferences using SharedPreferences.Editor

If you want to save something (String, setting, value...) in SharedPreferences, such that it can be retrieved later after Activity exited, we can use SharedPreferences.Editor.

Example:

package com.example.androidsharedpreferences;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

public class MainActivity extends Activity {
 
 String[] dayOfWeek = {"Sunday", "Monday", "Tuesday",
   "Wednesday", "Thursday", "Friday", "Saturday"};
 
 EditText editText;
 Button buttonSave;
 Spinner spinner;
 
 SharedPreferences prefs;
 final String KEY_SavedText = "Saved Text";
 final String KEY_SavedSel = "Saved Selection";

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  editText = (EditText)findViewById(R.id.edittext);
  buttonSave = (Button)findViewById(R.id.save);
  spinner = (Spinner)findViewById(R.id.spinner);
  
  ArrayAdapter<String> adapter = 
   new ArrayAdapter<String>(this, 
    android.R.layout.simple_spinner_item, dayOfWeek);
  adapter.setDropDownViewResource(
   android.R.layout.simple_spinner_dropdown_item);
  spinner.setAdapter(adapter);
  
  //retrieve saved preferences
  prefs = getPreferences(MODE_PRIVATE);
  String prefsString = prefs.getString(KEY_SavedText, null);
  if(prefsString != null){
   editText.setText(prefsString);
  }
  int prefsInt = prefs.getInt(KEY_SavedSel, -1);
  if(prefsInt != -1){
   spinner.setSelection(prefsInt);
  }
  
  //Save EditText if buttonSave clicked
  buttonSave.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
    editor.putString(KEY_SavedText, editText.getText().toString());
    editor.commit();
   }
  });
  
  //Save Spinner selection
  spinner.setOnItemSelectedListener(new OnItemSelectedListener(){

   @Override
   public void onItemSelected(AdapterView<?> parent, View view,
     int position, long id) {
    SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
    editor.putInt(KEY_SavedSel, position);
    editor.commit();
   }

   @Override
   public void onNothingSelected(AdapterView<?> parent) {}
  });

 }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidsharedpreferences.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    
    <EditText
        android:id="@+id/edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Save Text" />
    <Spinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

May 14, 2014

Display TextView with multi-color

This example show how to display TextView with multi-color, using Html.fromHtml() and SpannableString.

TextView with multi-color

package com.example.androidcolortext;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;
import android.widget.TextView.BufferType;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  TextView colorText1 = (TextView)findViewById(R.id.colortext1);
  String text1 = "<font COLOR=\'RED\'><b>" + "android-coding" + "</b></font>"
    + "<font COLOR=\'#00FF00\'><i>" + ".blogspot" + "</i></font>"
    + ".com";
  colorText1.setText(Html.fromHtml(text1));
  
  TextView colorText2 = (TextView)findViewById(R.id.colortext2);
  SpannableString text2 = new SpannableString("android-coding.blogspot.com");
  text2.setSpan(new ForegroundColorSpan(Color.RED), 0, 14, 0);
  text2.setSpan(new ForegroundColorSpan(Color.GREEN), 6, 11, 0);
  text2.setSpan(new ForegroundColorSpan(Color.BLUE), 15, text2.length(), 0);
  colorText2.setText(text2, BufferType.SPANNABLE);
  
  TextView colorText3 = (TextView)findViewById(R.id.colortext3);
  SpannableString text3 = new SpannableString("android-coding.blogspot.com");
  text3.setSpan(new BackgroundColorSpan(Color.LTGRAY), 0, text3.length(), 0);
  text3.setSpan(new ForegroundColorSpan(Color.RED), 0, 14, 0);
  text3.setSpan(new ForegroundColorSpan(Color.GREEN), 6, 11, 0);
  text3.setSpan(new ForegroundColorSpan(0xFF0000FF), 14, 23, 0);
  text3.setSpan(new ForegroundColorSpan(0x500000FF), 23, text3.length(), 0);
  colorText3.setText(text3, BufferType.SPANNABLE);

 }

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidcolortext.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    
    <TextView
        android:id="@+id/colortext1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="50sp" />
    <TextView
        android:id="@+id/colortext2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="50sp" />
    <TextView
        android:id="@+id/colortext3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="50sp" />

</LinearLayout>

May 13, 2014

ComposePathEffect vs SumPathEffect

This example show different effect of ComposePathEffect vs SumPathEffect, on CornerPathEffect and DashPathEffect.


/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidview.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="CornerPathEffect radius" />

    <SeekBar
        android:id="@+id/radius"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="500"
        android:progress="30" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="DashPathEffect phase" />

    <SeekBar
        android:id="@+id/phase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="30" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ToggleButton
            android:id="@+id/combineffect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textOff="SumPathEffect"
            android:textOn="ComposePathEffect" />

        <RadioGroup
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
            <RadioButton
                android:id="@+id/styleFill"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="FILL"
                android:checked="true" />
            <RadioButton
                android:id="@+id/styleStroke"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="STROKE" />
            <RadioButton
                android:id="@+id/styleFillAndStroke"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="FILL_AND_STROKE" />
        </RadioGroup>
    </LinearLayout>

    <com.example.androidview.MyView
        android:id="@+id/myview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MyView.java
package com.example.androidview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposePathEffect;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.SumPathEffect;
import android.graphics.Path.Direction;
import android.graphics.PathEffect;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paintBorder, paintCircle;
 Path pathBorder, pathCircle;
 
 Path pathShape;
 float cornerRadius;
 float dashPhase;
 float[] intervals = {50.0f, 50.0f};
 
 //true: ComposePathEffect
 //false: SumPathEffect
 boolean combinPathEffect; 
 
 Paint.Style style = Paint.Style.FILL;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paintBorder = new Paint();
  paintBorder.setColor(Color.BLUE);
  paintBorder.setStrokeWidth(5);
  
  paintCircle = new Paint();
  paintCircle.setColor(Color.RED);
  paintCircle.setStrokeWidth(5);

  pathBorder = new Path();
  pathCircle = new Path();
  
  pathShape = new Path();
  pathShape.moveTo(0, 0);
  pathShape.lineTo(10, 20);
  pathShape.lineTo(20, 0);
  pathShape.close();
  
  cornerRadius = 30.0f;
  dashPhase = 30.0f;
 }

 @SuppressLint("DrawAllocation")
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  pathBorder.reset();
  pathBorder.moveTo(50,  50);
  pathBorder.lineTo(50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, 50);
  pathBorder.close();
  
  float radius;
  pathCircle.reset();
  if(getWidth()>getHeight()){
   radius = getHeight()/4;
  }else{
   radius = getWidth()/4;
  }
  pathCircle.addCircle(getWidth()/2, getHeight()/2, radius, Direction.CCW);

  CornerPathEffect cornerPathEffect = new CornerPathEffect(cornerRadius);
  DashPathEffect dashPathEffect = new DashPathEffect(intervals, dashPhase);
  
  PathEffect pathEffect;
  
  if(combinPathEffect){
   pathEffect = new ComposePathEffect(dashPathEffect, cornerPathEffect);
  }else{
   pathEffect = new SumPathEffect(dashPathEffect, cornerPathEffect);
  }
  
  paintBorder.setStyle(style);
  paintCircle.setStyle(style);
  
  paintBorder.setPathEffect(pathEffect);
  paintCircle.setPathEffect(pathEffect);
  
  canvas.drawPath(pathBorder, paintBorder);
  canvas.drawPath(pathCircle, paintCircle);
 }
 
 public void setCornerRadius(float r){
  cornerRadius = r;
  invalidate();
 }
 public void setDashPhase(float p){
  dashPhase = p;
  invalidate();
 }
 
 public void setCombinPathEffect(boolean e){
  combinPathEffect = e;
  invalidate();
 }
 
 public void setStyle(Paint.Style s){
  style = s;
  invalidate();
 }

}

MainActivity.java
package com.example.androidview;

import android.app.Activity;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.ToggleButton;

public class MainActivity extends Activity {
 
 private MyView myView;
 private SeekBar seekBarRadius, seekBarPhase;
 ToggleButton buttonEffect;
 RadioButton radioFill, radioStroke, radioFillAndStroke;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  myView = (MyView)findViewById(R.id.myview);
  
  seekBarRadius = (SeekBar)findViewById(R.id.radius);
  seekBarRadius.setOnSeekBarChangeListener(seekBarRadiusChangeListener);
  seekBarPhase = (SeekBar)findViewById(R.id.phase);
  seekBarPhase.setOnSeekBarChangeListener(seekBarPhaseChangeListener);
  
  buttonEffect = (ToggleButton)findViewById(R.id.combineffect);
  buttonEffect.setOnCheckedChangeListener(buttonEffectCheckedChangeListener);
  
  radioFill = (RadioButton)findViewById(R.id.styleFill);
  radioStroke = (RadioButton)findViewById(R.id.styleStroke);
  radioFillAndStroke = (RadioButton)findViewById(R.id.styleFillAndStroke);
  radioFill.setOnCheckedChangeListener(radioOnCheckedChangeListener);
  radioStroke.setOnCheckedChangeListener(radioOnCheckedChangeListener);
  radioFillAndStroke.setOnCheckedChangeListener(radioOnCheckedChangeListener);
 }
 
 OnSeekBarChangeListener seekBarRadiusChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setCornerRadius(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
  
 };
 
 OnSeekBarChangeListener seekBarPhaseChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setDashPhase(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}
    @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
   
 };
 
 OnCheckedChangeListener buttonEffectCheckedChangeListener =
  new OnCheckedChangeListener(){

   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    myView.setCombinPathEffect(isChecked);
   }};
   
 OnCheckedChangeListener radioOnCheckedChangeListener =
  new OnCheckedChangeListener(){

   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    if(radioFill.isChecked()){
     myView.setStyle(Paint.Style.FILL);
    }else if(radioStroke.isChecked()){
     myView.setStyle(Paint.Style.STROKE);
    }else{
     myView.setStyle(Paint.Style.FILL_AND_STROKE);
    }
   }
  
 };
 
}


- More examples of drawing path on custom View.

May 11, 2014

Fill path and stroke with different color

Check the demo video. The outter (deviated) rectangle drawn with Paint with style of Paint.Style.FILL_AND_STROKE, both the filled area and stroke have the same color. The inner (deviated) circle drawn in two times; first time drawn with Paint.Style.FILL to fill the inner area, the second time draw with Paint.Style.STROKE to draw the stroke with different color.


package com.example.androidview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DiscretePathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paintBorder, paintCircle;
 Path pathBorder, pathCircle;
 
 Path pathShape;
 float segmentLength;
 float deviation;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paintBorder = new Paint();
  paintBorder.setColor(Color.BLUE);
  paintBorder.setStrokeWidth(20);
  paintBorder.setStyle(Paint.Style.FILL_AND_STROKE);
  
  paintCircle = new Paint();
  paintCircle.setStrokeWidth(20);

  pathBorder = new Path();
  pathCircle = new Path();
  
  pathShape = new Path();
  pathShape.moveTo(0, 0);
  pathShape.lineTo(10, 20);
  pathShape.lineTo(20, 0);
  pathShape.close();
  
  segmentLength = 30.0f;
  deviation = 30.0f;
 }

 @SuppressLint("DrawAllocation")
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  pathBorder.reset();
  pathBorder.moveTo(50,  50);
  pathBorder.lineTo(50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, 50);
  pathBorder.close();
  
  float radius;
  pathCircle.reset();
  if(getWidth()>getHeight()){
   radius = getHeight()/4;
  }else{
   radius = getWidth()/4;
  }
  pathCircle.addCircle(getWidth()/2, getHeight()/2, radius, Direction.CCW);

  DiscretePathEffect discretePathEffect =
    new DiscretePathEffect(segmentLength, deviation);
  paintBorder.setPathEffect(discretePathEffect);
  
  canvas.drawPath(pathBorder, paintBorder);
  
  //fill circle with color
  paintCircle.setColor(Color.RED);
  paintCircle.setStyle(Paint.Style.FILL);
  paintCircle.setPathEffect(discretePathEffect);
  canvas.drawPath(pathCircle, paintCircle);
  //draw stroke with different color
  paintCircle.setColor(Color.BLACK);
  paintCircle.setStyle(Paint.Style.STROKE);
  paintCircle.setPathEffect(discretePathEffect);
  canvas.drawPath(pathCircle, paintCircle);
  
 }
 
 public void setDeviation(int dev){
  deviation = (float)dev;
  invalidate();
 }
 
 public void setSegmentLength(int seglen){
  
  //force segmentLength not 0
  if (seglen==0){
   seglen = 1;
  }
   
  segmentLength = (float)seglen;
  invalidate();
 }
 
 public void setStrokeWidth(int strwidth){
  paintBorder.setStrokeWidth(strwidth);
  paintCircle.setStrokeWidth(strwidth);
  invalidate();
 }

}


Other files, /res/layout/activity_main.xml and MainActivity.java, refer to last post DiscretePathEffect example.

- More examples of drawing path on custom View.


May 10, 2014

DiscretePathEffect example

android.graphics.DiscretePathEffect chop the path into lines of segmentLength, randomly deviating from the original path by deviation.


Main layout, /res/layout/activity_main.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidview.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="segmentLength"/>
    <SeekBar 
        android:id="@+id/segmentLength"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="30"/>
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="deviation"/>
    <SeekBar 
        android:id="@+id/deviation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="30"/>
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="strokeWidth"/>
    <SeekBar 
        android:id="@+id/strokeWidth"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="20"/>
    
    <com.example.androidview.MyView
        android:id="@+id/myview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java
package com.example.androidview;

import android.app.Activity;
import android.graphics.PathDashPathEffect;
import android.graphics.PathDashPathEffect.Style;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;

public class MainActivity extends Activity {
 
 private MyView myView;
 private SeekBar seekBarSegmentLength, seekBarDeviation;
 private SeekBar seekBarStrokeWidth;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  myView = (MyView)findViewById(R.id.myview);
  
  seekBarSegmentLength = (SeekBar)findViewById(R.id.segmentLength);
  seekBarSegmentLength.setOnSeekBarChangeListener(seekBarSegmentLengthChangeListener);
  seekBarDeviation = (SeekBar)findViewById(R.id.deviation);
  seekBarDeviation.setOnSeekBarChangeListener(seekBarDeviationChangeListener);
  
  seekBarStrokeWidth = (SeekBar)findViewById(R.id.strokeWidth);
  seekBarStrokeWidth.setOnSeekBarChangeListener(seekBarStrokeWidthChangeListener);
 }
 
 OnSeekBarChangeListener seekBarSegmentLengthChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setSegmentLength(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
  
 };
 
 
 
 OnSeekBarChangeListener seekBarDeviationChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setDeviation(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}
    @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
   
 };
 
 OnSeekBarChangeListener seekBarStrokeWidthChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setStrokeWidth(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}
    @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
   
 };
 
}

MyView.java
package com.example.androidview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DiscretePathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paintBorder, paintCircle;
 Path pathBorder, pathCircle;
 
 Path pathShape;
 float segmentLength;
 float deviation;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paintBorder = new Paint();
  paintBorder.setColor(Color.BLUE);
  paintBorder.setStrokeWidth(20);
  paintBorder.setStyle(Paint.Style.STROKE);
  
  paintCircle = new Paint();
  paintCircle.setColor(Color.RED);
  paintCircle.setStrokeWidth(20);
  paintCircle.setStyle(Paint.Style.STROKE);

  pathBorder = new Path();
  pathCircle = new Path();
  
  pathShape = new Path();
  pathShape.moveTo(0, 0);
  pathShape.lineTo(10, 20);
  pathShape.lineTo(20, 0);
  pathShape.close();
  
  segmentLength = 30.0f;
  deviation = 30.0f;
 }

 @SuppressLint("DrawAllocation")
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  pathBorder.reset();
  pathBorder.moveTo(50,  50);
  pathBorder.lineTo(50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, 50);
  pathBorder.close();
  
  float radius;
  pathCircle.reset();
  if(getWidth()>getHeight()){
   radius = getHeight()/4;
  }else{
   radius = getWidth()/4;
  }
  pathCircle.addCircle(getWidth()/2, getHeight()/2, radius, Direction.CCW);

  DiscretePathEffect discretePathEffect =
    new DiscretePathEffect(segmentLength, deviation);
  paintBorder.setPathEffect(discretePathEffect);
  paintCircle.setPathEffect(discretePathEffect);
  
  canvas.drawPath(pathBorder, paintBorder);
  canvas.drawPath(pathCircle, paintCircle);

 }
 
 public void setDeviation(int dev){
  deviation = (float)dev;
  invalidate();
 }
 
 public void setSegmentLength(int seglen){
  
  //force segmentLength not 0
  if (seglen==0){
   seglen = 1;
  }
   
  segmentLength = (float)seglen;
  invalidate();
 }
 
 public void setStrokeWidth(int strwidth){
  paintBorder.setStrokeWidth(strwidth);
  paintCircle.setStrokeWidth(strwidth);
  invalidate();
 }

}

- More examples of drawing path on custom View.

May 9, 2014

Effect of advance, phase, style in PathDashPathEffect

The example make PathDashPathEffect with interactive setting of advance, phase and style; such that you can know how they affect the result.


Main layout, /res/layout/activity_main.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.androidview.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-coding.blogspot.com" />
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="advance"/>
    <SeekBar 
        android:id="@+id/advance"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="30"/>
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="phase"/>
    <SeekBar 
        android:id="@+id/phase"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="30"/>
    <Spinner
        android:id="@+id/style"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    
    <com.example.androidview.MyView
        android:id="@+id/myview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

MainActivity.java
package com.example.androidview;

import android.app.Activity;
import android.graphics.PathDashPathEffect;
import android.graphics.PathDashPathEffect.Style;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;

public class MainActivity extends Activity {
 
 private MyView myView;
 private SeekBar seekBarAdvance, seekBarPhase;
 private Spinner spinnerStyle;
 
 private String[] styleNames ={
  "PathDashPathEffect.Style.MORPH",
  "PathDashPathEffect.Style.ROTATE",
  "PathDashPathEffect.Style.TRANSLATE"};
 private Style[] styleSettings = {
  PathDashPathEffect.Style.MORPH,
  PathDashPathEffect.Style.ROTATE,
  PathDashPathEffect.Style.TRANSLATE};
 
 private ArrayAdapter<String> spinnerStyleAdapter;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  myView = (MyView)findViewById(R.id.myview);
  
  seekBarAdvance = (SeekBar)findViewById(R.id.advance);
  seekBarAdvance.setOnSeekBarChangeListener(seekBarAdvanceChangeListener);
  seekBarPhase = (SeekBar)findViewById(R.id.phase);
  seekBarPhase.setOnSeekBarChangeListener(seekBarPhaseChangeListener);
  
  spinnerStyle = (Spinner)findViewById(R.id.style);
  spinnerStyleAdapter = new ArrayAdapter<String>(this, 
   android.R.layout.simple_spinner_item, styleNames);
  spinnerStyleAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
  spinnerStyle.setAdapter(spinnerStyleAdapter);
  spinnerStyle.setOnItemSelectedListener(spinnerStyleOnItemSelectedListener);

 }
 
 OnSeekBarChangeListener seekBarAdvanceChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setAdvance(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}

   @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
  
 };
 
 OnSeekBarChangeListener seekBarPhaseChangeListener =
  new OnSeekBarChangeListener(){

   @Override
   public void onProgressChanged(SeekBar seekBar, int progress,
     boolean fromUser) {
    myView.setPhase(progress);
   }

   @Override
   public void onStartTrackingTouch(SeekBar seekBar) {}
    @Override
   public void onStopTrackingTouch(SeekBar seekBar) {}
  
 };
 
 OnItemSelectedListener spinnerStyleOnItemSelectedListener =
  new OnItemSelectedListener(){

   @Override
   public void onItemSelected(AdapterView<?> parent, View view,
     int position, long id) {
    myView.setStype(styleSettings[position]);
   }

   @Override
   public void onNothingSelected(AdapterView<?> parent) {
    // TODO Auto-generated method stub
    
   }
 };
 
}

MyView.java
package com.example.androidview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paint;
 Path pathBorder, pathCircle;
 
 Path pathShape;
 float phase;
 float advance;
 PathDashPathEffect.Style style;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paint = new Paint();
  paint.setColor(Color.BLUE);
  paint.setStrokeWidth(20);
  paint.setStyle(Paint.Style.STROKE);

  pathBorder = new Path();
  pathCircle = new Path();
  
  pathShape = new Path();
  pathShape.moveTo(0, 0);
  pathShape.lineTo(10, 20);
  pathShape.lineTo(20, 0);
  pathShape.close();
  
  phase = 30.0f;
  advance = 30.0f;
  style = PathDashPathEffect.Style.MORPH;
 }

 @SuppressLint("DrawAllocation")
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  pathBorder.reset();
  pathBorder.moveTo(50,  50);
  pathBorder.lineTo(50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, getHeight()-50);
  pathBorder.lineTo(getWidth()-50, 50);
  pathBorder.close();
  
  float radius;
  pathCircle.reset();
  if(getWidth()>getHeight()){
   radius = getHeight()/4;
  }else{
   radius = getWidth()/4;
  }
  pathCircle.addCircle(getWidth()/2, getHeight()/2, radius, Direction.CCW);

  PathDashPathEffect pathDashPathEffect =
    new PathDashPathEffect(pathShape, advance, phase, style);
  paint.setPathEffect(pathDashPathEffect);
  
  canvas.drawPath(pathCircle, paint);
  canvas.drawPath(pathBorder, paint);

 }
 
 public void setAdvance(int adv){
  advance = (float)adv;
  invalidate();
 }
 
 public void setPhase(int ph){
  phase = (float)ph;
  invalidate();
 }
 
 public void setStype(PathDashPathEffect.Style sty){
  style = sty;
  invalidate();
 }

}


- Running PathDashPathEffect example

- More examples of drawing path on custom View.

May 8, 2014

Running PathDashPathEffect example

This example implement running PathDashPathEffect, by varying phase parameter.


Modify MyView.java from the post.

package com.example.androidview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.PathDashPathEffect;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paint;
 Path path;
 
 Path pathShape;
 float phase;
 float advance;
 PathDashPathEffect.Style style;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paint = new Paint();
  paint.setColor(Color.RED);
  paint.setStrokeWidth(20);
  paint.setStyle(Paint.Style.STROKE);

  path = new Path();
  
  pathShape = new Path();
  pathShape.addCircle(10, 10, 10, Direction.CCW);
  
  phase = 0;
  advance = 30.0f;
  style = PathDashPathEffect.Style.ROTATE;

 }

 @SuppressLint("DrawAllocation")
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  path.reset();
  path.moveTo(50,  50);
  path.lineTo(50, getHeight()-50);
  path.lineTo(getWidth()-50, getHeight()-50);
  path.lineTo(getWidth()-50, 50);
  path.close();
  
  phase++;
  PathDashPathEffect pathDashPathEffect =
    new PathDashPathEffect(pathShape, advance, phase, style);
  paint.setPathEffect(pathDashPathEffect);
  
  canvas.drawPath(path, paint);
  
  invalidate();
 }

}


- Effect of advance, phase, style in PathDashPathEffect

- More examples of drawing path on custom View

May 7, 2014

PathDashPathEffect example

android.graphics.PathDashPathEffect dash the drawn path by stamping it with the specified shape.

Example:
PathDashPathEffect example
PathDashPathEffect example

Modify MyView.java from the post.
package com.example.androidview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.PathDashPathEffect;
import android.util.AttributeSet;
import android.view.View;

public class MyView extends View {

 Paint paint;
 Path path;

 public MyView(Context context) {
  super(context);
  init();
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MyView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  paint = new Paint();
  paint.setColor(Color.RED);
  paint.setStrokeWidth(20);
  paint.setStyle(Paint.Style.STROKE);

  path = new Path();
  
  Path pathShape = new Path();
  pathShape.addCircle(10, 10, 10, Direction.CCW);
  
  float advance = 30.0f;
  float phase = 20.0f;
  PathDashPathEffect.Style style = PathDashPathEffect.Style.ROTATE;
  
  PathDashPathEffect pathDashPathEffect =
   new PathDashPathEffect(pathShape, advance, phase, style);
  
  paint.setPathEffect(pathDashPathEffect);

 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawColor(Color.GRAY);

  path.reset();
  path.moveTo(50,  50);
  path.lineTo(50, getHeight()-50);
  path.lineTo(getWidth()-50, getHeight()-50);
  path.lineTo(getWidth()-50, 50);
  path.close();
  
  canvas.drawPath(path, paint);
 }

}

Infolinks In Text Ads