Thursday, May 28, 2015

Check if we are in Dual Pane

This is a common problem and with a variety of solutions. In the solution I'll show you in a little while we check in our Activity if there is an id for the 2nd Fragment ( the one that will play the role of the DetailFragment ).

One common tactic is having two different versions of the xml layout we are wokring on. One in the layout folder and another one in the layout-sw600dp or whatever we define for the dual mode.

The 2nd file contains one more FrameLayout so what we basically have to do is check if the view is there. If its true then we are on a dual mode, if not then we are on a single mode.

First we define a Boolean isDualMode with false as an initial value.
Then on onCreate we check for the details id :  

View aView = findViewById(R.id.details);
if (aView != null) {
    isDualPane = true;
}

If thats true we add and commit the DetailsFragment also.

Full code for onCreate() :

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


        View aView = findViewById(R.id.details);
        if (aView != null) {
            isDualPane = true;
        }

        android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
        android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        mainFragment = new MainFragment();

        if (isDualPane) {
            detailsFragment = new DetailsFragment();
            fragmentManager.beginTransaction().add(R.id.details, detailsFragment).commit();
        }

        fragmentManager.beginTransaction().add(R.id.main, mainFragment).commit();
        fragmentTransaction.commit();

    }

Thursday, May 21, 2015

Set text size for Toolbar

Since Toolbar doesnt provide a textSize attribute to set the text size of the Title you have to add a TextView and pass the title text to it.
Ofcourse you can instead use setTitleTextAppearance where you can set color, size, style etc.

For the first solution the steps you got to follow are :


1) remove default title :
    getSupportActionBar().setDisplayShowTitleEnabled(false);

2) Add TextView in Toolbar :

    <android.support.v7.widget.Toolbar
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:minHeight="?android:attr/actionBarSize"
        android:layout_width="match_parent"
        android:layout_height="@dimen/toolbar_height"
        android:background="@color/colorPrimary"
        android:theme="@style/ActionBarThemeOverlay"
       android:popupTheme="@style/ActionBarPopupThemeOverlay">

    <TextView
        android:id="@+id/tv_toolbar"
        android:textSize="@dimen/toolbar_textSize"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</android.support.v7.widget.Toolbar>

3) Set toolbar_textSize on dimens.xml :

<dimen name="toolbar_textSize">16sp</dimen>


Now toolbar's title size is the one you specify on the dimens.xml  file. That's it 16sp in our code.
We prefer sp units (instead of dp) so the size can scale when user changes the font size on her/his device.

Thursday, May 15, 2014

ActionBar dissapears although I'm using a scrollView

ActionBar dissapears when I click EditText although I'm using a ScrollView. This behavior appears after an orienation change when I click the EditText view.

Solution :
Seems that I need to add also  adjustResize on my manifest :
            android:windowSoftInputMode="adjustResize"

    //TODO
    further investigate that behavior

Sunday, February 23, 2014

ToDo List example

Since repetition is the mother of all learning and the following example is one of the most distinct examples of how to start android development I wrote it down as well to try to explain it as best as I can.

What we are going to do is a ToDo List app.

Bearing the design in mind will help us better understand what components will be needed ( plus I prefer a more visualized approach to such kind of problems ).

android todo app

As we can see from the mockup sketch two fragments are needed. One will just display an EditText widget and when the user clicks 'Send' on the software keyboard we will pass the text to the list bellow. That gets us to the second fragment which is a ListFragment.


Both of them are in the MainActivity.
Since we are using a ListFragment we have to use an Adapter to bind the data to the list.

Also we will need a data model for our todo items. Lets name it DataItem class.
Last but not least we will create a custom view from each list item.

Let me summarize things a little bit : We have one MainActivity class with its layout, composed of two fragments ( one is a ListFragment ). The ListFragment also needs an Adapter class. Our data model will only need a String variable and a Custom View for each ListFragment's item for the time.


So let's start from our model. We only need one getter and one setter method since our only variable will be a String. You can check the code here .

Now its time to create the TopFragment. As you can see 
<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" tools:context=".TopFragment" > <EditText android:id="@+id/myEditText1" android:inputType="textCapSentences|textAutoCorrect" android:imeOptions="actionSend" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" /> </LinearLayout>
 the layout is just an EditText. We inflate that layout in onCreateView method ( like we do with every fragment ). The “tricky” part here is adding an OnEditorActionListener  so we can listen for the 'SEND' action, get the user input and clear the text in EditText. An Interface is also necessary so we can implement it on the MainActivity and get the user's text input. All of these data will be stored on an ArrayList in the MainActivity and passed to the Adapter to bind them to the view.  


The TaskListAdapter gets each item from the ArrayList as we said above, creates a new list item and sets the data.

ListFragment just inflates the layout which consists of a ListView with the android:divider atrribute set to null so we don't have to deal with the default divider line from the ListView widget.


Since each item is just a TextView our custom view needs to extend a TextView. We saw on a previous post  how to create a custom view so I will not go into details.

The XML layout file for the custom view, used by the TaskListAdapter is:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".TaskListFragment" > <org.codeteo.todolist.CustomItemView android:id="@+id/row" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:textColor="#FF0000" android:textSize="20sp" /> </LinearLayout>


Now we have to check the MainActivity code. The MainActivity implements the OnItemAddedListener Interface we declared on the TopFragment and create the method onNewItemAdded() so it can get the data user's input and store it on an ArrayList.
That input along with the id resource of the XML file that represents the list
item are passed to the Adapter.
The code is below :

 public class MainActivity extends Activity  implements TopFragment.OnItemAddedListener {
 
   private ArrayList todoItems;
   private TaskListAdapter aa; 

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
       
     // Get references to the Fragments
     FragmentManager fm = getFragmentManager();
     TaskListFragment todoListFragment = 
       (TaskListFragment)fm.findFragmentById(R.id.TaskListFragment);
      
     // Create the array list of to do items
     todoItems = new ArrayList();
      
     // Create the array adapter to bind the array to the ListView
     int resID = R.layout.tasklist_fragment;   
     aa = new TaskListAdapter(this, resID, todoItems);
      
     // Bind the array adapter to the ListView.
     todoListFragment.setListAdapter(aa);
   }
   
   public void onNewItemAdded(String newItem) {
     DataItem newTodoItem = new DataItem(newItem);
     todoItems.add(0, newTodoItem);
     aa.notifyDataSetChanged();
   }
}


The method onNewItemAdded() adds the DataItem before every other ArrayList item and also notify the data set has changed.
You can find the code of the project in the github repo here and you can import it and run it on your eclipse.
This example is based on Reto Meier's example on chapter four of his book "Professional Android 4 Application Development" you can find in this link

Sunday, December 29, 2013

Custom Views

We get Custom Views by extending an existing Widget ( Button, EditText, TextView, etc ), something that fits better to the functionality we want to achieve and by defining attributes for that view.

1. By extending a View we now have a Class, whose fully qualified name can be used as an XML tag, to add to the layout file. If the package is com.androidexamples.customviews and my Custom View's Class name is MyEditText then the XML code we are going to add is :

<com.androidexamples.customviews.MyEditText
    android:id=”@+id/myview”
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
        …

/>

2. Into res/values/attrs.xml inside a <declare-styleable> tag we add the attributes for our view. A valid example could be :

<resources>
        <declare-styleable>
            <attr name=”attr_color” format=”color” />
            <attr name=”attr_firstname” format=”string” />
       </declare-styleable>
</resources>


From now on we can use these attributes either in our layout file as part of our custom View XML tag, or through code.
In order to use them in the layout file we have to first define a custom namespace similar to what android does with its own attributes. The android default namespace is : xmlns:android="http://schemas.android.com/apk/res/androidand it's defined into the parent element of the layout file.
Respectively our attributes' namespace uses the same format but instead of android we can use whatever name we want ( like “app” or “custom” ) and the schema is defined with our package name instead of the android. So a valid example could be :
xmlns:app="http://schemas.android.com/apk/res/com.androidexamples.customviews"

Now we can add the “attr_firstname” to the XML in the form : 
                       app:attr_firstname=”Some Random Text”


Through the code we have access to an array that stores each attribute. It is a special container named TypedArray and it can get referenced to the attributes with obtainStyledAttributes().


3. In our Class code it is a common practise to use an init() method to get the attributes and assign initial values to them. This method is then passed to our View's constructor.

4. Then all it's left to do is to override the onDraw() and onMeasure() methods.


By overriding onDraw() we have access to the Canvas object. You can now create your UI for your View. The styling of the elements is done through a Paint object.


OnMeasure() is called with the width and height specifications from the parent layout element. Those values should be treated as requirements for the restrictions on width and height measurements we will produce.


Some key points you should keep in mind ( otherwise it leads you to hard ) :
  • call recycle() after you get the attributes from TypedArray.
  • Don't create Paint objects inside onDraw() method. Views are redrawn frequently and creating objects inside onDraw() its expensive waste of resources.
  • After every change on our attributes' values we have to call invalidate() so the system will know there might be a change in its appearance and needs to be redrawn.



The code below gives as a custom EditText which uses Paint to underline each line with a light green color.




public class MyEditText extends EditText {

 private Rect mRect;
 private Paint mPaint;
  
 private int attrColor;
 
 
 public MyEditText(Context context) {
  super(context);
 }

 public MyEditText(Context context, AttributeSet attrs) {
  super(context, attrs);
  
  TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyEditText);
     attrColor = ta.getInteger(R.styleable.MyEditText_attr_color, 0xff00ff00);
     ta.recycle();
  
  init();
 }

 public void init() {
  
  mRect = new Rect();
  mPaint = new Paint();
  mPaint.setStyle(Paint.Style.FILL);
  mPaint.setColor(attrColor);    //get value from attr
  
 }
 
 
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  int count = getLineCount();
  
  Rect r = mRect;
  Paint p = mPaint;
  
  
 for(int i=0; i< count; i++)  {
   int baseline = getLineBounds(i, r);
   canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, p);
  }
  
 }
 
}



Monday, December 9, 2013

Add Views programmatically

Example of adding two Buttons in a RelativeLayout :

1) Instantiate the RelativeLayout
2) Instantiate the Buttons.
3) Create the LayoutParams for each Buttons.
4) Add Views to their parent. That's the RelativeLayout.

One key point here. The LayoutParams for the child Views must the same type as that of their parent. So in our case both Buttons  LayoutParams have to be RelativeLayout.LayoutParams.

Let's see how this applies to code :

RelativeLayout layout = new RelativeLayout(this); // Instantiate the parent

b3 = new Button(this); b3.setId(1);
b3.setText("Relative Button 3");

b4 = new Button(this); b4.setId(2);
b4.setText("Relative Button 4");

RelativeLayout.LayoutParams b3_lp = new RelativeLayout.LayoutParams(
                   LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);


RelativeLayout.LayoutParams b4_lp = new RelativeLayout.LayoutParams(
                  LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
b4_lp.addRule(RelativeLayout.RIGHT_OF, b3.getId());

layout.addView(b3, b3_lp);
layout.addView(b4, b4_lp);

setContentView(layout);


The result is :



Notice the addRule() which sets the Button b4 to the right of the b3.
To achieve that we have to set Id's for our Buttons so we can refer to the view that acts as an anchor.



Sunday, November 24, 2013

Send JSON unicode data to server with POST request

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url); // Address ( url )
HttpResponse response;

JSONObject json = new JSONObject();

json.put("passwd", param1);
json.put("comment", param2);

                        // String Entity to UTF-8
StringEntity se = new StringEntity(json.toString(), "UTF-8");
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));

httppost.getParams().setParameter("json", json);
httppost.setEntity(se);

response = httpclient.execute(httppost);