viernes, 28 de agosto de 2015

Android: Expandable list group icon

drawable/groupindicator_icon
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_expanded="true" android:drawable="@drawable/arrow_up" />
    <item android:drawable="@drawable/arrow_down" />
</selector>
The images have to be 9 patch images, like the following:

Align icon to the right
@Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        DisplayMetrics metrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int width = metrics.widthPixels;
        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
            listView.setIndicatorBounds(width-getPixelFromDips(HORIZONTAL_PADDING*2)-getPixelFromDips(35), width-getPixelFromDips(HORIZONTAL_PADDING*2-getPixelFromDips(5)));
        } else {
            listView.setIndicatorBoundsRelative(width-getPixelFromDips(HORIZONTAL_PADDING*2)-getPixelFromDips(35), width-getPixelFromDips(HORIZONTAL_PADDING*2)-getPixelFromDips(5));
        }
    }

    public int getPixelFromDips(float pixels) {
        final float scale = getResources().getDisplayMetrics().density;
        return (int) (pixels * scale + 0.5f);
    }
Note: If you get a "No resource found..." even when the 9 patch is there it is because the 9 patch is not properly created.

jueves, 27 de agosto de 2015

Android: Shadow effect on background (spinner background shadow effect)


android:background="@android:drawable/dialog_holo_light_frame"

Android: Expandable list, group divider and child divider

Layout
<ExpandableListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:groupIndicator="@drawable/group_indicator_icon"
            android:divider="@color/orange"
            android:dividerHeight="1dp"
            android:childDivider="#b4b6b9"/>
Adapter
@Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    } // If it returns false the child divider won't appear
If you want to hide the group indicator for empty groups:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/transparent" android:state_expanded="true" android:state_empty="true" />
    <item android:state_expanded="true" android:drawable="@drawable/arrow_up" />
    <item android:drawable="@drawable/arrow_down" />
</selector>
Order is important, keep it as the example above.

Android: Usefull intents (phone, email, browser)

Phone
Intent intent = new Intent(Intent.ACTION_CALL);
                intent.setData(Uri.parse("tel:" + phoneNumber)); // "phoneNumber" is a string
                context.startActivity(intent);
Email
Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
                        "mailto", email, null)); // "email" is the recipients email address
                emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
                emailIntent.putExtra(Intent.EXTRA_TEXT, "Body");
                context.startActivity(Intent.createChooser(emailIntent, context.getString(R.string.send_email)));
Browser
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webURL));
                context.startActivity(browserIntent);

Android: Clickable text in TextView

In this case it is just a URL that can be clicked, it can be anything and do anything:
final String webURL = facilityInformation.getWeb();

        TextView web = (TextView) convertView.findViewById(R.id.website);
        Spannable span = Spannable.Factory.getInstance().newSpannable(webURL);
        span.setSpan(new ClickableSpan() {
            @Override
            public void onClick(View v) {
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webURL));
                context.startActivity(browserIntent);
            }
        }, 0, webURL.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        web.setMovementMethod(LinkMovementMethod.getInstance());
        web.setText(span);

        return convertView;
Note:
- 0 and webURL.length() define the piece of the text that can be clicked.
- To set the link color you just add the following as an attribute to the TextView: "android:textColorLink="<color>""

jueves, 20 de agosto de 2015

Android: Adding / replacing fragments (Fragments backstack)


public void pushFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).addToBackStack(null).commit();
    }

    public void replaceFragment(Fragment fragment) {
        FragmentManager manager = getSupportFragmentManager();

        for (int i = 0; i < manager.getBackStackEntryCount(); i++) {
            manager.popBackStack();
        }

        manager.beginTransaction().replace(R.id.container, fragment, FRAGMENT).commit();
    }

Android: Change "home" icon

getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.settings);

martes, 18 de agosto de 2015

Android: Spinner adapter


public class SpinnerAdapter extends BaseAdapter {

    private Context context;
    private List<Object> items;

    public FacilitySpinnerAdapter(Context context, List<Object> items) {
        this.context = context;
        this.items = items;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public Object getItem(int position) {
        return items.get(position);
    }

    @Override
    public long getItemId(int position) {
        return getItem(position).getId();
    }
// View to be displayed when the spinner is closed
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.closed_row, null);
        }

        //...

        return convertView;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.drop_down_row, null);
        }

        //...

        return convertView;
    }
}

miércoles, 12 de agosto de 2015

Android: Change HomeUsUpIndicator drawable

If you use a toolbar as an action bar: Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); ... setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeAsUpIndicator(R.drawable.my_home_us_up_indicator_drawable); If you use regular action bar:

Android: Get image from device

Use
private void setProfilePictureOnClickListener() {

        profileImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);
            }
        });
    }
@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);

                LoadImage task = new LoadImage();
                addTask(task);
                task.execute();
            }
        }
    }

    public String getPath(Uri uri) {

        String realPath;

        if (Build.VERSION.SDK_INT < 11) {
            realPath = RealPathUtil.getRealPathFromURI_BelowAPI11(this, uri);

        } else if (Build.VERSION.SDK_INT < 19) {
            realPath = RealPathUtil.getRealPathFromURI_API11to18(this, uri);

        } else {
            realPath = RealPathUtil.getRealPathFromURI_API19(this, uri);
        }

        return realPath;
    }
RealPathUtil
public class RealPathUtil {

    @SuppressLint("NewApi")
    public static String getRealPathFromURI_API19(Context context, Uri uri) {
        String filePath = "";
        String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String id = wholeID.split(":")[1];

        String[] column = {MediaStore.Images.Media.DATA};

        // where id is equal to
        String sel = MediaStore.Images.Media._ID + "=?";

        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                column, sel, new String[]{id}, null);

        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
        return filePath;
    }


    @SuppressLint("NewApi")
    public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        String result = null;

        CursorLoader cursorLoader = new CursorLoader(context, contentUri, proj, null, null, null);
        Cursor cursor = cursorLoader.loadInBackground();

        if (cursor != null) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            result = cursor.getString(column_index);
        }
        cursor.close();
        return result;
    }

    public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(column_index);
        cursor.close();
        return path;
    }
}

martes, 11 de agosto de 2015

Android: Webview


Make links open in my webview rather than default browser:

private void setLinks(View view) {

        String linksAsText = getLinksAsText();

        linksContainerView = view.findViewById(R.id.links_container);
        linksContainerView.setVisibility(linksAsText.isEmpty() ? View.GONE : View.VISIBLE);

        linksTextView = (TextView) view.findViewById(R.id.links);
        linksTextView.setText(linksAsText);
        linksTextView.setMovementMethod(LinkMovementMethod.getInstance());
        linksTextView.setLinksClickable(true);
        setTextViewHTML(linksTextView, getLinksAsText());
    }

private String getLinksAsText() {

        StringBuilder builder = new StringBuilder();

        for (String link : feed.getLinks()){
            builder.append("<br>");
            builder.append("<html>");
            builder.append("<a href=\"");
            builder.append(link);
            builder.append("\">");
            builder.append(link);
            builder.append("</a></html>");
        }

        String linksText = builder.toString();

        return linksText.isEmpty() ? "" : linksText.substring(4);
    }


private void setTextViewHTML(TextView text, String html)
    {
        CharSequence sequence = Html.fromHtml(html);
        SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
        URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);

        for(URLSpan span : urls) {
            makeLinkClickable(strBuilder, span);
        }

        text.setText(strBuilder);
    }

    private void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
    {
        int start = strBuilder.getSpanStart(span);
        int end = strBuilder.getSpanEnd(span);
        int flags = strBuilder.getSpanFlags(span);

        ClickableSpan clickable = new ClickableSpan() {
            public void onClick(View view) {
                openUrlInWebView(span);
            }
        };
        strBuilder.setSpan(clickable, start, end, flags);
        strBuilder.removeSpan(span);
    }

    private void openUrlInWebView(URLSpan span) {
        Bundle bundle = new Bundle();
        bundle.putString(WebViewFragment.URL, span.getURL());

        WebViewFragment fragment = new WebViewFragment();
        fragment.setArguments(bundle);

        getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment).addToBackStack(null).commit();
    }
WebViewFragment class
public class WebViewFragment extends BaseFragment {


    public static String URL = "url";

    private WebView webView;
    private ProgressDialog progressDialog;
    private int counter;

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

        progressDialog = new ProgressDialog(getActivity());
        progressDialog.setMessage(getString(R.string.loading));
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_video_tour, null);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        webView = (WebView) view.findViewById(R.id.webview);

        startWebView(getArguments().getString(URL));
    }

    private void startWebView(String url) {

        webView.setWebViewClient(new WebViewClient() {

            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);

                counter++;

                if (!progressDialog.isShowing()) {
                    progressDialog.show();
                }
            }

            public void onPageFinished(WebView view, String url) {

                counter--;

                if (counter == 0) {
                    progressDialog.dismiss();
                }
            }

        });

        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setLoadWithOverviewMode(true);
        webView.getSettings().setUseWideViewPort(true);

        // Other webview options
        /*
        webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        webView.setScrollbarFadingEnabled(false);
        webView.getSettings().setBuiltInZoomControls(true);
        */

        webView.loadUrl(url);
    }
}
WebViewFragment layout
<RelativeLayout 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" >

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>
Usage
Bundle bundle = new Bundle();
bundle.putString(VideoTourFragment.URL, <string_URL>);

VideoTourFragment fragment = new VideoTourFragment();
fragment.setArguments(bundle);

lunes, 3 de agosto de 2015

Android Studio: Adding dependencies

In your project's build.gradle (inside your app's folder, on the outermost).

...

dependencies {
    compile 'com.google.code.gson:gson:2.2.4'    
    compile 'com.android.support:appcompat-v7:22.2.0'    
    compile 'com.android.support:design:22.2.0'    
    compile 'com.android.support:support-v4:22.2.0'    
    compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
}