Android Custom Farsi Font for Views Using Calligraphy Library

build.gradle

dependencies {
    compile 'uk.co.chrisjenx:calligraphy:2.2.0'
}

Add Application Class :
MyApplication.java

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
                .setDefaultFontPath("fonts/BYekan.ttf")
                .setFontAttrId(R.attr.fontPath)
                .build());
    }
}

Register your Application Class :
AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ir.mhdr.a072">

    <application
        android:allowBackup="true"
        android:name=".MyApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Add attachBaseContext to all Activities

MainActivity.java

public class MainActivity extends AppCompatActivity {

    NumberPicker numberPicker;

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

        numberPicker= (NumberPicker) findViewById(R.id.numberPicker);
        numberPicker.setMinValue(0);
        numberPicker.setMaxValue(99);
        numberPicker.setValue(24);
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(CalligraphyContextWrapper.wrap(base));
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/073
https://github.com/chrisjenx/Calligraphy
https://blog.goyello.com/2014/08/01/how-to-use-custom-fonts-in-android-apps-and-not-get-fat-3/

Android Custom Farsi Font for Views Using TypeFace

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="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="ir.mhdr.a071.MainActivity">

    <TextView
        android:id="@+id/textViewMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World 12!"
        android:layout_below="@+id/numberPicker"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="115dp" />

    <ir.mhdr.a071.CustomNumberPicker
        android:id="@+id/numberPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="center" />

</RelativeLayout>

CustomNumberPicker.java

public class CustomNumberPicker extends NumberPicker {

    public CustomNumberPicker(Context context) {
        super(context);
    }

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

    public CustomNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void addView(View child) {
        super.addView(child);

        updateView(child);
    }

    @Override
    public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
        super.addView(child, index, params);
        updateView(child);
    }

    @Override
    public void addView(View child, android.view.ViewGroup.LayoutParams params) {
        super.addView(child, params);
        updateView(child);
    }

    private void updateView(View view) {

        Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "fonts/BNazanin.ttf");

        if(view instanceof EditText) {
            ((EditText) view).setTypeface(typeface);
        }

        if (view instanceof TextView)
        {
            ((TextView) view).setTypeface(typeface);
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    TextView textViewMessage;
    CustomNumberPicker numberPicker;

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

        textViewMessage = (TextView) findViewById(R.id.textViewMessage);

        // the base way to do this in android
        // the font is placed on assets/fonts/BNazanin.ttf
        Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/BNazanin.ttf");
        textViewMessage.setTypeface(typeface);


        // for other views we need to extend view
        numberPicker = (CustomNumberPicker) findViewById(R.id.numberPicker);
        numberPicker.setMinValue(0);
        numberPicker.setMaxValue(99);
        numberPicker.setValue(34);
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/071

Android Working with NumerPicker

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="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="ir.mhdr.a070.MainActivity">

    <NumberPicker
        android:id="@+id/numberPicker2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="166dp" />
</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    NumberPicker numberPicker;

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

        numberPicker= (NumberPicker) findViewById(R.id.numberPicker2);
        numberPicker.setMaxValue(99);
        numberPicker.setMinValue(0);
        numberPicker.setValue(25);
        numberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/070

Android Connect to Google Drive and Save a file

1 – Create a New Project on Google Developer Console
2 – Enable Google Drive API
Then :
build.gradle

compile 'com.google.android.gms:play-services-drive:10.2.1'

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ir.mhdr.a068">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data android:name="com.google.android.gms.games.APP_ID" android:value="@string/app_id" />
        <meta-data android:name="com.google.android.gms.appstate.APP_ID" android:value="@string/app_id" />
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version"/>
    </application>

</manifest>

MainActivity.java

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final int REQUEST_CODE_CREATOR = 1;
    private static final int REQUEST_CODE_RESOLUTION = 2;
    private GoogleApiClient mGoogleApiClient;

    Button buttonSave;

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

        buttonSave= (Button) findViewById(R.id.buttonSave);

        buttonSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveFileToDrive();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mGoogleApiClient == null) {
            // Create the API client and bind it to an instance variable.
            // We use this instance as the callback for connection and connection
            // failures.
            // Since no account name is passed, the user is prompted to choose.
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(Drive.API)
                    .addScope(Drive.SCOPE_FILE)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
        }

        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause() {
        if (mGoogleApiClient != null) {
            mGoogleApiClient.disconnect();
        }
        super.onPause();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionSuspended(int i) {


    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // Called whenever the API client fails to connect.
        if (!result.hasResolution()) {
            // show the localized error dialog.
            GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show();
            return;
        }
        // The failure has a resolution. Resolve it.
        // Called typically when the app is not yet authorized, and an
        // authorization
        // dialog is displayed to the user.
        try {
            result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
        } catch (IntentSender.SendIntentException e) {
            e.printStackTrace();
        }
    }

    /**
     * Create a new file and save it to Drive.
     */
    private void saveFileToDrive() {
        // Start by creating a new contents, and setting a callback.

        Drive.DriveApi.newDriveContents(mGoogleApiClient)
                .setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {

                    @Override
                    public void onResult(DriveApi.DriveContentsResult result) {
                        // If the operation was not successful, we cannot do anything and must fail
                        if (!result.getStatus().isSuccess()) {
                            return;
                        }
                        // Otherwise, we can write our data to the new contents.

                        // Get an output stream for the contents.
                        OutputStream outputStream = result.getDriveContents().getOutputStream();
                        Writer writer=new OutputStreamWriter(outputStream);

                        try {
                            writer.write("Hello World");
                            writer.flush();
                            writer.close();
                        } catch (IOException e1) {
                            e1.printStackTrace();
                        }
                        // Create the initial metadata - MIME type and title.
                        // Note that the user will be able to change the title later.
                        MetadataChangeSet metadataChangeSet = new MetadataChangeSet
                                .Builder()
                                .setMimeType("text/plain")
                                .setTitle("Hello.txt")
                                .setStarred(true)
                                .build();

                        // Create an intent for the file chooser, and start it.
                        IntentSender intentSender = Drive.DriveApi
                                .newCreateFileActivityBuilder()
                                .setInitialMetadata(metadataChangeSet)
                                .setInitialDriveContents(result.getDriveContents())
                                .build(mGoogleApiClient);

                        try {
                            startIntentSenderForResult(
                                    intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
                        } catch (IntentSender.SendIntentException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/068

Android Sync ViewPager with BottomNavigationView

MainActivity.java

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

     // set selected item
     bottomNavigationView.getMenu().getItem(1).setChecked(true);
     viewPagerMain.setCurrentItem(1);

     // bind bottomNavigationView and viewPager
     bottomNavigationView.setOnNavigationItemSelectedListener(bottomNavigationView_OnNavigationItemSelectedListener);
     viewPagerMain.addOnPageChangeListener(viewPagerMain_OnPageChangeListener);
 }
BottomNavigationView.OnNavigationItemSelectedListener bottomNavigationView_OnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
     @Override
     public boolean onNavigationItemSelected(@NonNull MenuItem item) {

         switch (item.getItemId()) {
             case R.id.item_bn_graph:
                 viewPagerMain.setCurrentItem(0);
                 break;
             case R.id.item_bn_bmi:
                 viewPagerMain.setCurrentItem(1);
                 break;
             case R.id.item_bn_table:
                 viewPagerMain.setCurrentItem(2);
                 break;
         }

         return true;
     }
 };

 ViewPager.OnPageChangeListener viewPagerMain_OnPageChangeListener = new ViewPager.OnPageChangeListener() {
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

     }

     @Override
     public void onPageSelected(int position) {
         switch (position) {
             case 0:
                 bottomNavigationView.getMenu().getItem(0).setChecked(true);
                 break;
             case 1:
                 bottomNavigationView.getMenu().getItem(1).setChecked(true);
                 break;
             case 2:
                 bottomNavigationView.getMenu().getItem(2).setChecked(true);
                 break;
         }
     }

     @Override
     public void onPageScrollStateChanged(int state) {

     }
 };

References
https://github.com/mhdr/AndroidSamples/tree/master/067

Android Open Navigation Drawer from Right

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawerLayout"
    android:layout_gravity="start"
    android:fitsSystemWindows="true"
    tools:openDrawer="end"
    tools:context="ir.mhdr.bmi.MainActivity">


    <!--Content-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include
            layout="@layout/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <RelativeLayout
            android:id="@+id/relativeLayoutMainContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.design.widget.BottomNavigationView
                android:id="@+id/bottomNavigationView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                app:itemBackground="@color/colorBottomNavigation"
                app:menu="@menu/bottom_navigation">

            </android.support.design.widget.BottomNavigationView>

        </RelativeLayout>

    </RelativeLayout>

    <!--Drawer-->
    <android.support.design.widget.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="end">

    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    DrawerLayout drawerLayout;
    Toolbar toolbar;
    ActionBarDrawerToggle actionBarDrawerToggle;

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

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ViewCompat.setLayoutDirection(toolbar, ViewCompat.LAYOUT_DIRECTION_RTL);
        getSupportActionBar().setTitle(R.string.app_name_fa);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
        drawerLayout.addDrawerListener(actionBarDrawerToggle);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        actionBarDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        actionBarDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        // it will not work for right to left navigation drawer
/*        if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }*/


        // so we have to open and close the navigation drawer ourselves
        if(item.getItemId() == android.R.id.home) {
            if(drawerLayout.isDrawerOpen(Gravity.END)) {
                drawerLayout.closeDrawer(Gravity.END);
            }
            else {
                drawerLayout.openDrawer(Gravity.END);
            }
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/065

Android Right to Left Toolbar

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Toolbar toolbar;

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

        toolbar= (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ViewCompat.setLayoutDirection(toolbar,ViewCompat.LAYOUT_DIRECTION_RTL);
    }
}

References
https://github.com/mhdr/AndroidSamples/tree/master/064