Using Custom Widgets in during editing the Android DataGrid

clock April 13, 2015 22:19 by author Administrator

As we saw in the previous blog post, each cell in the DataGrid can be customized to render a custom widget within it. This also holds true for the edit mode version of each cell. When the grid is put into edit mode, we draw a row of editors on top of the grid and place editors for each editable column in place of the cell. So this looks like:

 

 

In this example, we are going to replace the editor for one of the columns with a Spinner. The default editor is a Text Input. Using a spinner means we have to do the following things:

 

1) Make sure we specify the itemEditor in the markup:

                itemEditor="com.flexicious.mysampleapp.SpinnerEditor"

 2) MAke sure we tell the grid that we are using a custom editor, so we will take care of populating it from the data, and populating the data back from it: 

                itemEditorManagesPersistence="true"

 

 3) Implement the itemEditorInitialize and Commit Functions

            //because we have a custom spinner as an editor, we need to write code to

            //populate it when the spinner loads, and then take the value from the spinner

            //when the user clicks ok button. The following two functions will accomplish this task

            grid.rowEditBehavior.itemEditorsInitializeFunction= new Function(this,"initializeEditors");

            grid.rowEditBehavior.itemEditorsCommitFunction= new Function(this,"commitEditors");

 

       /**

       * This method is responsible for taking the values from the editors, and making sure

       * that the values are applied to the row data on click OK of the editor row.

       * @param editors A Map of the unique identifier of the column the editor belongs to, and the editor

       */

      public void commitEditors(HashMap<String,Object> editors){

            FlexDataGrid grid = (FlexDataGrid) findViewById(R.id.flexDataGrid);

            Object itemBeingEdited = grid.getCurrentEditingCell().getRowInfo().getData();

            for(String key : editors.keySet()){

                  View editor = (View) editors.get(key);

                  if(editor instanceof SpinnerEditor){

                        FlexDataGridColumn column = grid.getColumnByUniqueIdentifier(key);

                        SpinnerEditor spinnerEditor = (SpinnerEditor) editor;

                        UIUtils.setPropertyValue(itemBeingEdited, column.getDataField(), spinnerEditor.getSelectedItem());

                  }

            }

      }

      /**

       * This method is responsible for taking the values from the item being edited, and making sure

       * that the values are applied to the editors on load.

       * @param editors A Map of the unique identifier of the column the editor belongs to, and the editor

       */

      public void initializeEditors(HashMap<String,Object> editors){

            FlexDataGrid grid = (FlexDataGrid) findViewById(R.id.flexDataGrid);

            Object itemBeingEdited = grid.getCurrentEditingCell().getRowInfo().getData();

            for(String key : editors.keySet()){

                  View editor = (View) editors.get(key);

                  if(editor instanceof SpinnerEditor){

                        //is this our spinner editr?

                        FlexDataGridColumn column = grid.getColumnByUniqueIdentifier(key);

                        SpinnerEditor spinnerEditor = (SpinnerEditor) editor;

                    Object compareValue = UIUtils.resolveExpression(itemBeingEdited, column.getDataField());

                    //get the value from the item being edited

                    if(compareValue!=null)

                    {

                        //apply this value.

                          ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinnerEditor.getAdapter();

                              int spinnerPostion = adapter.getPosition((String) compareValue);

                          spinnerEditor.setSelection(spinnerPostion);

                    }

                  }

            }

      }

 

Thats it! This gives you a lot of control over the kind of item editors you can use. and the logic you want to associate with them!. Full code attached.

 

 

project.zip (153.87 kb)



Android DataGrid Vertical Header Text

clock April 12, 2015 04:58 by author Administrator

One of the most powerful features of the Android DataGrid product is the ability to control the content of each cell that sits inside the grid. 

 Inside each cells is the actual component that renders the content of the cell. These are represented by the following properties on the column or the level

  •  
    • itemRenderer
    • headerRenderer
    • footerRenderer
    • pagerRenderer
    • filterRender
    • nextLevelRenderer


       The above properties point to class factories for item renderer instances that display the data for each item in the column. You can specify a ClassFactory custom item renderer component as the value of these properties. The default item renderer is a Label class, which displays the item data as text.


If specifying custom label text is not enough for your needs, you can use itemRenderers, which is a very powerful concept. Item Renderers are basically UIComponents that sit inside the various cells of the grid.  

In this example, we are going to specify a custom header renderer that renders the text vertically. This is what it will look like:

 



 

How do we do this? Just look at the code in red:

<?xml version="1.0" encoding="UTF-8"?>

<grid

    enableExport="true"

    enableFilters="true"

    enableFooters="true"

    enablePreferencePersistence="true"

    enablePrint="true"

    forcePagerRow="true"

    pageSize="50"

    enablePaging="true">

 

    <level>

        <columns>

            <column

                dataField="label"

                headerText="Name"

                filterControl="TextInput"

                filterOperation="Contains"

                headerRenderer="com.flexicious.mysampleapp.ItemRenderers_VerticalTextRenderer"

                footerLabel="Count: " footerOperation="count" footerOperationPrecision="3"/>

            <column

                dataField="data"

                headerText="Type"

                filterControl="TextInput"

                headerRenderer="com.flexicious.mysampleapp.ItemRenderers_VerticalTextRenderer"

                filterOperation="Contains"

                footerLabelFunction="customFooterFunction"

                />

        </columns>

    </level>

 

</grid>

 

 And the renderer:

package com.flexicious.mysampleapp;

 

public class ItemRenderers_VerticalTextRenderer extends TextView {

     

      final boolean topDown = false;

       

     

      public Object getData() {

            return data;

      }

 

      public void setData(Object data) {

      }

       

 

         @Override

         protected void onDraw(Canvas canvas){

            TextPaint textPaint = getPaint();

            textPaint.setColor(getCurrentTextColor());

            textPaint.drawableState = getDrawableState();

 

            canvas.save();

 

            if(topDown){

               canvas.translate(getWidth(), 0);

               canvas.rotate(90);

            }else {

               canvas.translate(0, getHeight());

               canvas.rotate(-90);

            }

 

 

            canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());

 

            getLayout().draw(canvas);

            canvas.restore();

        }

     

      private Object data;

 

}

 

 Full sample code:

MySampleApp.zip (157.35 kb)



Using JSON data with Xamarin

clock April 8, 2015 01:32 by author Administrator

As most of you are aware, our Android DataGrid has built in support for rendering JSON data. For example, you can use the following code in Java to show JSON 

/**
* Takes a grid, and an XML configuration, loads the XML configuration into the Grid.
* @param grid
* @param resource
*/
public void buildGrid(FlexDataGrid grid, Integer resource) {
            grid.delegate = this;
            BufferedReader reader = new BufferedReader(new InputStreamReader(this.getResources().openRawResource(resource)));
            StringBuilder builder = new StringBuilder();
            String aux = "";
            try {
                  while ((aux = reader.readLine()) != null) {
                        builder.append(aux);
                  }
            } catch (IOException e) {
                  throw new RuntimeException(e);
            } 

            String text = builder.toString();
            flexDataGrid.buildFromXml(text);
      }

 

      /**
       * Parses json data and passes it to the grid to display
       * @param grid
       * @param resource
       */
      public void loadJsonData(FlexDataGrid grid, Integer resource) {
            BufferedReader jsonReader = new BufferedReader(new InputStreamReader(
                        this.getResources().openRawResource(resource)));
            StringBuilder jsonBuilder = new StringBuilder();
            try {
                  for (String line = null; (line = jsonReader.readLine()) != null;) {
                       jsonBuilder.append(line).append("\n");
                  }
            } catch (IOException e) {
                  throw new RuntimeException(e);
            }

 

            // Parse Json
            this.flexDataGrid.setDataProviderJson(jsonBuilder.toString());
      }

 

How would you do the same in c# Xamarin? Well, code is surprising similar:

[Activity (Label = "AndroidApp", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        int count = 1;
        FlexDataGrid flexDataGrid;

        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            // Set our view from the "main" layout resource
            SetContentView (Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById<Button> (Resource.Id.myButton);
            
            button.Click += delegate {
                button.Text = string.Format ("{0} clicks!", count++);
            };

            flexDataGrid = FindViewById<FlexDataGrid> (Resource.Id.flexDataGrid1);

            LoadJsonData(flexDataGrid, Resource.Raw.flxsdatamocknesteddata);
        
        } 
        public void LoadJsonData(FlexDataGrid grid, int resource)
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(this
                .Resources.OpenRawResource(resource)));
            StringBuilder builder = new StringBuilder();
            string aux = "";
            try {
                while ((aux = reader.ReadLine()) != null) {
                    builder.Append(aux);
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            string text = builder.ToString();
            grid.SetDataProviderJson (builder.ToString ());
        }
    }

 

Attached is a sample (you will need to place your copy of the bindings dll in it).

AndroidApp.zip (87.06 kb)



Xamarin Support - DataProvider Data Type

clock April 6, 2015 19:47 by author Administrator

Now that our latest build with Xamarin support is out, some of our customers had this question:

1. In your demo, you used NameValue as datasource, but it only generates two columns data, how do I produces more column? 

Well, basically the idea is to provide a class that inherits from Java.Lang.Object as the dataprovider to the grid, and expose its properties to the ACW using getters and exporting them.

Example:



    public class Employee : Java.Lang.Object
    {
        public string Name = "";
        public string PhoneNumber ="";
        public string Title ="";
        public string Address ="";

        [Java.Interop.Export("getName")]
        public string getName(){
            return this.Name;
        }
        [Java.Interop.Export("getPhoneNumber")]
        public string getPhoneNumber(){
            return this.PhoneNumber;
        }
        [Java.Interop.Export("getTitle")]
        public string getTitle(){
            return this.Title;
        }
        [Java.Interop.Export("getAddress")]
        public string getAddress(){
            return this.Address;
        }
    }

 

 

If you do this, you should be able to use the following XML and see the results:

      <column
          dataField="Name"
          headerText="Name" />
      <column
          dataField="PhoneNumber"
          headerText="PhoneNumber" />
    </columns>

 

 

Full code is attached to this post.

grid_config.xml (570.00 bytes)

MainActivity.cs (3.93 kb)



AndroidJetPack Team Blog


Tag cloud