Tuesday, December 24, 2013

How To Determine If Android Device Is a Tablet Or a Phone?

Setting your screen correctly for different size devices is one of the trickier things to get correct in Android.  The problem is that different devices report different sizes for the same screen size.  I've tried several different solutions for this and the best I found is one from Stackoverflow.

I added the code to a static method I can call where ever it is needed in the app.


public static boolean isTabletDevice(Context activityContext) 
{
        
        boolean xlarge = ((activityContext.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE);

        if (xlarge) 
        {
            DisplayMetrics metrics = new DisplayMetrics();
            Activity activity = (Activity) activityContext;
            activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

            if (metrics.densityDpi == DisplayMetrics.DENSITY_DEFAULT
                    || metrics.densityDpi == DisplayMetrics.DENSITY_HIGH
                    || metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM
                    || metrics.densityDpi == DisplayMetrics.DENSITY_TV
                    || metrics.densityDpi == DisplayMetrics.DENSITY_XHIGH) 
            {

                return true;
            }
        }

        return false;
}

Examples of how I've used this method can be found in the OpenStax College Android app.  The code is on Github. The method above is in the class OSCUtil. An example of using it is in the LandingActivity class.

Tuesday, September 3, 2013

Hiding Bottom Actionbar During Scrolling

Google introduced a design pattern of hiding the bottom Actionbar when the user is scrolling.  When the scrolling stops, the Actionbar is displayed.  The Google Plus app was the first app I saw use this pattern.  It is easy to add to your existing WebView.  This post assumes you already have an Actionbar setup at the bottom of your WebView.  If not, check out this post for a simple way to implement one in your layout.

The steps to implement are

  • Create an ObservableWebView
  • Modify WebView layout to use ObservableWebView
  • Add code in your Activity

Create an ObservableWebView


 The original code for this class can be found in this StackOverflow question 

public class ObservableWebView extends WebView
{
    private OnScrollChangedCallback mOnScrollChangedCallback;

    public ObservableWebView(final Context context)
    {
        super(context);
    }

    public ObservableWebView(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ObservableWebView(final Context context, final AttributeSet attrs, final int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt)
    {
        super.onScrollChanged(l, t, oldl, oldt);
        if(mOnScrollChangedCallback != null) 
     {
         mOnScrollChangedCallback.onScroll(l, t);
     }
    }

    public OnScrollChangedCallback getOnScrollChangedCallback()
    {
        return mOnScrollChangedCallback;
    }

    public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback)
    {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }

    /**
     * Impliment in the activity/fragment/view that you want to listen to the webview
     */
    public static interface OnScrollChangedCallback
    {
        public void onScroll(int l, int t);
    }
}

Modify WebView Layout 

 The modification is to use the ObservableWebView by name in the layout.

  
   
  
  
   
       
       
       
       
       
   
  

Add Code In Activity 

 I added code where I was setting up the WebView to have an OnScrollChangedCallback()

webView.setOnScrollChangedCallback(new OnScrollChangedCallback(){
            public void onScroll(int l, int t)
            {
             
             String url = content.getUrl().toString();
             float newY = webView.getScrollY();
                //Log.d("WebViewActivity", "newY: " +newY);
                //Log.d("WebViewActivity", "yPosition: " +yPosition);
             if(url.contains(getString(R.string.search)) || url.contains(getString(R.string.html_ext)))
                {
              hideToolbar();
                }
                else if(newY >= yPosition)
               {
                //hide layout
                hideToolbar();
               }
               else
               {
                //show toolbar
                showToolbar();
               }
               yPosition = newY;
            }
         });

The code for showToolbar() and hideToolbar() are below.



    private void hideToolbar()
    {
     RelativeLayout relLayout = (RelativeLayout)findViewById(R.id.relativeLayout1);
        int visibility = relLayout.getVisibility();

        if(visibility == View.VISIBLE)
        {
            relLayout.setVisibility(View.GONE);
        }
    }
    
    private void showToolbar()
    {
     RelativeLayout relLayout = (RelativeLayout)findViewById(R.id.relativeLayout1);
        int visibility = relLayout.getVisibility();
        if(visibility == View.GONE)
        {
            relLayout.setVisibility(View.VISIBLE);
        }
    }

You can get the code from our repository in GitHub. Connexions for Android is available in the Google Play Store.

Thursday, April 25, 2013

Adding a Spinner to ActionbarSherlock

A spinner is a dropdown on the Actionbar (see screenshot in this post).  It is a list of items that perform an action when selected.  It is fairly easy to add to your project using ActionbarSherlock.

There are a few steps to creating the Spinner

  • Create an XML resource file
  • Add Spinner to menu XML
  • Add Actionbar navigation code to onCreate() in the Activity using the Spinner
  • Adding code to handle Spinner items being selected
Create An XML Resource File

In the resource file, the items to be displayed should be listed. The file should be in res/values.  I named the file spinner_resources.xml


    
        Tools
        Android Design Guide Site
        Rate This App
    
Add Spinner to Menu XML

The XML added must reference the ActiobarSherlock Spinner object


    
    
    


Add Navigation Code


In the Activity.onCreate() method, a couple of lines need to be added to get a handle on the Actionbar and to set the navigation mode to list.
...
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
...

Code to Handle Spinner Selection

In the onCreateOptionsMenu() method, the code should

  • inflate the menu
  • add a spinner adapter
  • add a navigation listener to handle spinner selection

@Override
public boolean onCreateOptionsMenu(Menu menu) 
{
   getSupportMenuInflater().inflate(R.menu.actionbar_menu, menu);
            
   SpinnerAdapter mSpinnerAdapter;
   if(Build.VERSION.SDK_INT <= 10) 
   {
      mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.nav_list,android.R.layout.simple_spinner_item);
   }
   else
   {
      mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.nav_list,android.R.layout.simple_spinner_dropdown_item);
   }
   OnNavigationListener mOnNavigationListener = new OnNavigationListener() 
   {
      // Get the same strings provided for the drop-down's ArrayAdapter
      //String[] strings = getResources().getStringArray(R.array.nav_list);

      @Override
      public boolean onNavigationItemSelected(int position, long itemId) 
      {
         switch (position)
         {
             case 1:
                 Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://developer.android.com/design/index.html"));
                 startActivity(browserIntent);
                 break;
             case 2:
                 openPlayStore();
                 break;
          }
                  
          return true;
        }
     };
              
     actionBar.setListNavigationCallbacks(mSpinnerAdapter, mOnNavigationListener);
     return true;
}

Notice the code that switches the Spinner layout depending on the Android version.


Droid Design Guide is an open source app that has examples of using this feature. The code is in GitHub.

Saturday, February 16, 2013

Adding "Home as Up" Using ActionbarSherlock

"Home as Up" is part of the Actionbar design pattern in the Android Design Guide. This feature is part of an app when there is a small arrow to the left of the app icon in the Actionbar.  Implementation is simple. This post will use the ActionbarSherlock library.

In the Activities where the "Home as Up" should be displayed, in the onCreate() method get the Actionbar and then call setDisplayHomeAsUpEnabled(true)

...

ActionBar actionBar = getSupportActionBar();

actionBar.setDisplayHomeAsUpEnabled(true);

...


The second part of the implementation is to code what should happen if "Home as Up" is selected.  This is done in onOptionsItemSelected()

@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
     int itemId = item.getItemId();
     switch (itemId)
     {
         case R.id.ddg:
             Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://developer.android.com/design/index.html"));
             startActivity(browserIntent);
         case android.R.id.home:
             Intent mainIntent = new Intent(getApplicationContext(), MainActivity.class);
             mainIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
             startActivity(mainIntent);
         default:
             break;
     }

     return true;
 }

If you have an Activity where you do not want "Home as Up", set
setDisplayHomeAsUpEnabled(false);

If your app is written to have a tablet view (master/detail), "Home as Up" will not be displayed in landscape, but will be displayed in portrait.

Droid Design Guide is an open source app that has examples of using this feature. The code is in GitHub.