在低版本android系统上实现Material设计应用

Material Design真的很好看,动画效果真的很实用。前面也写了一些文章介绍如何编写Material风格的程序,但是很多都是一些新的api,低版本上面没有这些api,我们没办法使用。但是不用气馁,google官方,以及一些大牛,给我们提供了一些程序,让我们在低版本上面可以实现Material风格的程序,这里就给大家介绍一下。

妹子图截屏 继续阅读在低版本android系统上实现Material设计应用

创建Material Design风格的Android应用–使用自定义动画

动画在Material Design设计中给用户反馈放用户点击时,并且在程序用户界面中提供连贯的视觉。Material主题为按钮(Button)和activity的转换提供了一些默认的动画,在android5.0(api 21)和更高的版本,你可以自定义这些动画和创建一个新动画: 继续阅读创建Material Design风格的Android应用–使用自定义动画

创建Material Design风格的Android应用–使用Drawable

以下Drawables的功能帮助你在应用中实现Material Design:

图片资源着色

在android 5.0(api 21)和更高版本,可以着色bitmap和.9 png 通过定义透明度遮盖。你可以着色通过使用颜色资源或者主题的属性去解析颜色资源(比如,?android:attr/colorPrimary).通常我们创建一次,然后资源自适应主题。

你可以给BitmapDrawable或NinePatchDrawable对象着色使用setTint()方法。你可以可以在布局文件中使用android:tintandroid:tintMode属性设置着色颜色和着色模式。

从图片中抽取高亮颜色

support library r21和更高的版本中包括了Palette类,可以从一个图片中提取高亮颜色。这个类可以提起以下几种突出颜色:

Vibrant 充满生机

Vibrant dark 暗的充满生机

Vibrant light 亮的充满生机

Muted 柔和

Muted dark 暗的柔和

Muted light 亮的柔和

传递一个Bitmap对象给静态方法Palette.generate(),它会在后台线程帮你从后台线程提取颜色。如果你不能使用这个后台线程,使用Palette.generateAsync()方法,并且设置一个监听器listener.

你可以从图片中取得突出颜色使用Palette类中的getter方法,比如Palette.getVibrantColor.

在项目中使用Palette方法,需要在项目中包含v7包palette的jar, gradle dependecy添加的方式是:

...
compile 'com.android.support:palette-v7:21.0.+'

下面这个是示例代码:
java
Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
// Do something with colors...
palette.getVibrantColor(Color.BLACK); //get a color in rgb value
}
});

更多信息,请查看Paltette的api文档:http://developer.android.com/reference/android/support/v7/graphics/Palette.html

创建矢量drawables

在android 5.0和更高版本中,可以创建矢量的drawable,在缩放的时候不会失真。你只需要定义一个矢量图片文件,相反的,使用bitmap位图则需要针对不同的分辨率创建多个文件。创建一个矢量图片,你需要说明图形的详细,在xml文件的标签下。

下面是一个例子:

<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/heart.xml -->
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="256dp"
    android:height="256dp"
    android:viewportHeight="32"
    android:viewportWidth="32">

    <!-- draw a path -->
    <path
        android:fillColor="#f15467"
        android:pathData="M20.5,9.5
                        c-1.955,0,-3.83,1.268,-4.5,3
                        c-0.67,-1.732,-2.547,-3,-4.5,-3
                        C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5
                        c5.207,-5.242,9,-7.97,9,-11.5
                        C25,11.432,23.043,9.5,20.5,9.5z"/>
</vector>

上面的图显示效果如下:

矢量图片在android表现为VectorDrawable对象。更多信息,查看Svg Path reference。

参考资料:http://developer.android.com/training/material/drawables.html

原文地址:http://isming.me/2014/11/03/creating-app-with-material-design-four-drawables/,转载请注明出处。

创建Material Design风格的Android应用–定义阴影和裁剪视图

之前已经写过通过应用主题和使用ListView, CardView,应用Material Design样式,同时都都可以通过support library向下兼容。今天要写的阴影和视图裁剪,无法向下兼容,请注意。

​Material Design 为用户界面元素引入了深度这个元素。深度帮助用户理解各个元素之间的重要关联和帮助用户关注他们手上的任务。

视图的高度(elevation),通过Z属性表现,通过他的阴影确定:z值更高的视图投影出更大的阴影。视图只在Z=0的平面上投影处阴影;他们不会投影阴影在其他放在下面的视图上面和高于z=0的平面。

有更高Z值的视图挡住Z值较低的视图。无论如何,Z值不会影响到View的大小。

高度也是有用的,当在执行一些动作的时候创建动画让组件升起。

为视图分配高度

一个View的Z值有两个组成部分,elevation(高度)translation(平移).elevation是一个静态部分,translation 用于动画:

Z = elevation + translationZ

不同高度的视图的阴影

在布局文件中设置evelation 使用android:elevation,在代码中使用View.setElevation()方法。
设置一个视图的平移,使用View.setTranslationZ()方法。

新的方法ViewPropertyAnimator.z()ViewPropertyAnimator.translationZ()可以让你更容易的变动视图的高度。更多的信息,看ViewPropertyAnimator的Api文档http://developer.android.com/reference/android/view/ViewPropertyAnimator.html。和属性动画的开发指南:http://developer.android.com/guide/topics/graphics/prop-animation.html

你也可以使用StateListAnimator方式定义这些文件在xml文件中。特别适用于,状态改变时执行的动画,比如用户点击按钮。更多信息,请看动画视图状态改变,下次在动画一节讲。
Z值在测量上使用和X,Y值一样的单位。

自定义视图阴影和轮廓

视图的背景边界决定了阴影的默认形状。轮廓(Outlines)代表了图形对象的外形状,并确定了对触摸反馈区的波纹。

看这个视图,定义一个背景Drawable:

<TextView
    android:id="@+id/myview"
    ...
    android:elevation="2dp"
    android:background="@drawable/myrect" />

背景是一个圆角矩形

<!-- res/drawable/myrect.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#42000000" />
    <corners android:radius="5dp" />
</shape>

当这个背景drawable作为视图的轮廓,视图投射出圆角阴影。提供一个自定义的轮廓,可以覆盖默认视图阴影的形状。

在自己的代码中自定义一个轮廓:

1.继承ViewOutlineProvider类
2.重写getOutline()方法
3.在视图中设置轮廓,使用View.setOutlineProvider()方法

你可以创建椭圆和圆角矩形轮廓使用OutLine类中的方法。视图默认的outline provider会根据视图的背景来生成轮廓。可以设置视图的outline provider为null,来阻止投射阴影。

 裁剪视图

裁剪视图功能,可以让你更容易的改变视图的形状。你可以裁剪视图为了和其他的设计元素保持一致,或者改变成形状响应用户的输入。你可以裁剪一个视图的轮廓使用View.setClipToOutLine()方法,或者android:clipToOutline属性。只有矩形,圆角矩形,圆圈的轮廓支持被裁剪,可以使用Outline.canClip()方法检测是否支持被裁剪。

裁剪视图到一个drawable的形状,设置drawable作为视图的背景(让视图显示在其上),并且调用View.setClipToOutline()方法。

裁剪视图是一个耗费的操作,裁剪视图时不要使用形状动画。达到这种效果,请使用Reveal Effect 动画(下节讲)。

 总结

上面可以看到,设置阴影很简单:

  1. 设置eleavation值。
  2. 添加背景或者设置一个outline.

参考资料:http://developer.android.com/training/material/shadows-clipping.html

原文地址:http://isming.me/2014/10/26/creating-app-with-material-design-three-shadows/,转载请注明出处。

创建Material Design风格的Android应用–创建列表和卡片

上次说过使用主题,应用Material Design的样式,同时卡片布局也是Material Design的重要组成部分,今天来写写。

引言

在程序中创建复杂的Material Design 样式的 List和Card,可以使用RecyclerView和CardView组件,这两个组件是在最新的support v7包(version 21)中提供的。因此需要引入依赖包:

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile 'com.android.support:cardview-v7:+'
    compile 'com.android.support:recyclerview-v7:+'
}

创建List

RecylerView组件是一个更加高效灵活的ListView。这个组件时一个显示大数据集的容器,可以有效的滚动,保持显示一定数量的视图。使用RecyclerView组件,当你有数据集,并且数据集的元素在运行时根据用户的操作或者网络事件改变。

RecylerView类简化大数据集的显示和处理,通过提供:
布局管理者控制元素定位。
在通用的元素上操作上显示默认的动画,比如移除和增加元素。

使用RecyclerView组件,你需要指定一个Adapter和布局管理器,创建一个Adapter继承RecyclerView.Adapter类,具体的实现细节要根据数据集合视图的类型变化,具体信息,看下面的例子。

一个布局管理器定位Item视图在RecyclerView中,决定什么时候去回收它当他不再可见时。当重用(或者回收)一个视图时,布局管理器可能会请求适配器(Adapter)去替换子视图中的内容用不同的内容。通过这种方式回收重用视图,可以减少view的创建和避免更多的findViewById(),从而提高性能。

RecyclerView提供了以下内建的布局管理器:

LinearLayoutManager 显示Item 在一个水平或者垂直的滚动列表中。
GridLayoutManager 显示Item 作为网格布局。
StaggeredGridLayoutManager 显示Item在交错的网格布局。

也可以自己通过继承RecyclerView.LayoutManager类创建自定义的布局管理器。

RecylerView组件

RecylerView组件

动画:

RecyclerView默认情况下就有动画,在删除或者增加Ite的时候。如果需要自定义动画,继承RecyclerView.ItemAnimator类,并且使用RecyclerView.setItemAnimator()方法将定义的动画设置到我们的视图中。

下面开始看例子:
1.首先在xml布局文件增加一个RecyclerView
xml
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

2.然后在我们的Java代码中使用,附加Adapter和数据就可以显示了。

public class MyActivity extends Activity {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new MyAdapter(myDataset);
        mRecyclerView.setAdapter(mAdapter);
    }
    ...
}

3.Adapter提供访问数据集中的Item,创建视图映射到数据上,并且替换布局的内容数据用新的item。下面的代码显示一个简单的实现,使用TextView显示简单的String数组。
“`java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {<br/>
private String[] mDataset;</p>

<pre><code>// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ViewHolder(TextView v) {
super(v);
mTextView = v;
}
}

// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset) {
mDataset = myDataset;
}

// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_text_view, parent, false);
// set the view's size, margins, paddings and layout parameters

ViewHolder vh = new ViewHolder(v);
return vh;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// – get element from your dataset at this position
// – replace the contents of the view with that element
holder.mTextView.setText(mDataset[position]);

}

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.length;
}
</code></pre>

<p>}<br/>

<pre><code><br /><br /><br /><h3 id="toc_3">创建Card</h3>

<em>CardView</em>继承<em>FrameLayout</em>类,通过它可以显示信息在卡片内部,并且在不同的平台上有统一的样式。CardView组件可以有阴影和圆角。

创建有阴影的Card,使用<em>card_view:cardElevation</em>属性。CardView 使用真实的高度和动态阴影在Android5.0(API 21)和更高版本,较早的版本则使用传统的阴影。

使用这些属性去定制CardView的外观:

<blockquote>
使用<em>card_view:cardCornerRadius</em>属性设置圆角的半径,在布局文件中。<br />
使用<em>CardView.setRadius</em>方法设置圆角的半径在java代码中。<br />
设置卡片的背景颜色,使用<em>card_view:cardBackgroundColor</em>属性。
</blockquote>

下面是一个在xml布局文件中包含一个CardView的示例:<br />
“`xml<br />
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”<br/>
xmlns:tools=”http://schemas.android.com/tools”<br/>
xmlns:card_view=”http://schemas.android.com/apk/res-auto”<br/>
… ><br/>
<!– A CardView that contains a TextView –><br/>
<android.support.v7.widget.CardView<br/>
xmlns:card_view=”http://schemas.android.com/apk/res-auto”<br/>
android:id=”@+id/card_view”<br/>
android:layout_gravity=”center”<br/>
android:layout_width=”200dp”<br/>
android:layout_height=”200dp”<br/>
card_view:cardCornerRadius=”4dp”></p>

<pre><code> <TextView
android:id=”@+id/info_text”
android:layout_width=”match_parent”
android:layout_height=”match_parent” />
</android.support.v7.widget.CardView>
</code></pre>

<p></LinearLayout><br/>

Card示例图

Card示例图

乱弹

通过上面可以看到RecyclerView。跟我们经常使用的ListView很像,不过它的父类并不是AbsListView,因此不能混着使用。但是在很多地方可以替换ListView,通过ViewHolder,View重用,可以看到这是一个更加高效的视图组件,推荐使用。

CardView,本质上就是一个比较符合Material Design的组件,使用Card布局,效果更好。很多人之前可能也使用一些CardUi,谷歌官方出了这个,强烈推荐使用。

上面RecyclerView和CardView,是分开写的,但是我们可以用在一起的哦,不要糊涂了呀。

参考资料:http://developer.android.com/training/material/lists-cards.html

原文地址:http://blog.isming.me/2014/10/21/creating-app-with-material-design-two-list/,转载请注明出处。

创建Material Design风格的Android应用–应用主题

昨天正式发布了android 5,同时android developer网站也更新了,增加了创建Material Design风格的Android应用指南,也更新了Support Library,在support library增加了一些Material Design风格的控件和动画等,这里给大家简单介绍一下怎样开发material design风格的Android应用。

android 5使用Material Design风格

android提供了三种Material Design风格Theme。

分别是:

@android:style/Theme.Material (dark version)        
@android:style/Theme.Material.Light (light version)     
@android:style/Theme.Material.Light.DarkActionBar   

Light material theme

Light material theme

Dark material theme

Dark material theme

我们可以以这三个Theme来定义我们的Theme,比如:
xml
<resources>
<!-- inherit from the material theme -->
<style name="AppTheme" parent="android:Theme.Material">
<!-- Main theme colors -->
<!-- your app branding color for the app bar -->
<item name="android:colorPrimary">@color/primary</item>
<!-- darker variant for the status bar and contextual app bars -->
<item name="android:colorPrimaryDark">@color/primary_dark</item>
<!-- theme UI controls like checkboxes and text fields -->
<item name="android:colorAccent">@color/accent</item>
</style>
</resources>

我们可以修改每个位置的字或者背景的颜色,每个位置的名字如下图所示:

Customizing the material theme

我就简单的介绍一下,更具体的自己探索吧。

较低版本使用Material Design风格

要在较低版本上面使用Material Design风格,则需要使用最新的support library(version 21),可以直接把项目引入工程,或者使用gradle构建,增加compile dependency:

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile 'com.android.support:cardview-v7:+'
    compile 'com.android.support:recyclerview-v7:+'
}

将上面的AppTheme style放到res/values-v21/style.xml,再res/values/style.xml增加一个AppTheme,如下:

<!-- extend one of the Theme.AppCompat themes -->
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- customize the color palette -->
    <item name="colorPrimary">@color/material_blue_500</item>
    <item name="colorPrimaryDark">@color/material_blue_700</item>
    <item name="colorAccent">@color/material_green_A200</item>
</style>

这样可以同样实现很多的地方是Material Design,但是由于低版本不支持沉浸式状态栏,有一些效果还是无法实现。

PS:就写这么多吧。下次写使用CardView 和RecyclerView。做Material Design的List 和Card布局。 (我英文不好,可能有些地方也理解的不好。)

参考:http://developer.android.com/training/material/theme.html

原文地址:http://isming.me/2014/10/18/creating-android-app-with-material-design-one-theme/,转载请注明出处。

Android中个人推崇的数据库使用方式

手机应用开发中经常会使用到数据库存储一些资料或者进行数据缓存,android中为我们提供了一个轻量的数据库,在上层进行了一层封装,同时还为我们提供了ContentProvider的框架,方便我们进行数据操作,以及在不同的程序之间进行数据共享。本文介绍一下,我在使用数据库的一些我认为比较好的习惯,欢迎与我讨论。

关于框架

通常网络操作,Json解析,我都会使用框架,这样可以很好的帮助我处理异常,处理异步操作。但是数据库操作我则使用自带的SQLiteHelper和ContentProvider,这样android系统在SQLite上为我们提供的一层封装。因此,我不再使用第三方的SQLite框架。SQLiteDatabase和ContentProvider为我们提供一下函数

query()  //查询
insert() //插入
delete()  //删除
update()  //更新
//参数和返回值我没有写

可以看到,android为我们提供的操作已经被封装了,很多地方和别的ORM框架也是有一些类似的。而且在android中我们通常不会存储非常复杂的数据结构,没必要给自己学习框架增加成本。

 数据库建库升级等原则

先看一段代码

private final class DatabaseHelper extends SQLiteOpenHelper {
        public DatabaseHelper(final Context context) {
            super(context, DB_NAME, null, DB_VERSION);
        }
        
        /**
        * 1-->2 add header table
        * 2-->3 update info
        * 3--> update info haha
        *
        */
        public static final int DB_VERSION = 4;
        public static final String DB_NAME = "download";

        /**
         * Creates database the first time we try to open it.
         */
        @Override
        public void onCreate(final SQLiteDatabase db) {
            if (Constants.LOGVV) {
                Log.v(Constants.TAG, "populating new database");
            }
            onUpgrade(db, 0, DB_VERSION);
        }

        /**
         * Updates the database format when a content provider is used
         * with a database that was created with a different format.
         *
         * Note: to support downgrades, creating a table should always drop it first if it already
         * exists.
         */
        @Override
        public void onUpgrade(final SQLiteDatabase db, int oldV, final int newV) {

            for (int version = oldV + 1; version <= newV; version++) {
                upgradeTo(db, version);
            }
        }

        /**
         * Upgrade database from (version - 1) to version.
         */
        private void upgradeTo(SQLiteDatabase db, int version) {
            switch (version) {
                case 1:
                    createDownloadsTable(db);
                    break;
                case 2:
                    createHeadersTable(db);
                    break;
                case 3:
                    addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_IS_PUBLIC_API,
                              "INTEGER NOT NULL DEFAULT 0");
                    addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOW_ROAMING,
                              "INTEGER NOT NULL DEFAULT 0");
                    addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES,
                              "INTEGER NOT NULL DEFAULT 0");
                    break;
                case 103:
                    addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI,
                              "INTEGER NOT NULL DEFAULT 1");
                    makeCacheDownloadsInvisible(db);
                    break;
                case 4:
                    addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT,
                            "INTEGER NOT NULL DEFAULT 0");
                    break;
                default:
                    throw new IllegalStateException("Don't know how to upgrade to " + version);
            }
        }

以上代码是摘自android 中的DownloadProvider的DatabaseHelper代码。我在这里主要是像推荐这种数据库的建表,最初接触这种建表方式是在以前阅读DownloadManager的时候发现,发现android中这种设计真的是非常精妙。这种方式,方便数据库的升级,在update数据库和create数据库的时候,可以共用建表,修改数据表的代码,同时可以清晰看到数据库的变化。

同时建议,在修改数据库版本的时候,在版本号上面增加注释,写上数据库升级的内容,方便自己以后看到数据库的变化,以及其他人在看代码时候,了解到数据库的变化。

数据库建表和数据存储建议

一些简单的配置文件,不建议存到数据库,存到sharepreference中,方便存取,同时也提高访问速度。

文件,图片等绝对不要存到数据库,存储文件路径到数据库中即可。

一些很复杂的数据,建议直接转成json存到数据库即可。一些缓存也可以这样存储。

其他要说的

数据库操作时候,不要在主线程操作。这是耗时操作,容易造成ANR.

在进行数据库中的数据显示时候,建议配合CursorLoader使用,这是android提供的异步数据加载,同时会在数据变化时候,自动重新刷新数据。

其他,本文,本人乱扯。如有你有异议,欢迎回复讨论。

原文地址:http://isming.me/2014/10/13/good-database-use/,转载请注明出处。

在android中画圆形图片的几种办法

在开发中经常会有一些需求,比如显示头像,显示一些特殊的需求,将图片显示成圆角或者圆形或者其他的一些形状。但是往往我们手上的图片或者从服务器获取到的图片都是方形的。这时候就需要我们自己进行处理,将图片处理成所需要的形状。正如茴香豆的的“茴”写法大于一种,经过我的研究,画出特殊图片的方法也不是一种,我发现了三种,且听我一一道来。

使用Xfermode 两图相交方式

通过查找资料发现android中可以设置画笔的Xfermode即相交模式,从而设置两张图相交之后的显示方式,具体模式见下图,源码可以去android apidemo。(SRC 为我们要画到目标图上的图即原图,DST为目标图)

由上图可以看到,如果我们需要画一个圆形的图,可以在画布上面先画一个跟目标大小一样的圆,然后xfermode选择SRC_IN,再讲我们的头像或者其他图画上去就可以了。同样也可以先画我们的图,再画圆,不过xfermode要选择DST_IN。两种都可以实现我们需要的效果。示例代码如下:

Paint p = new Paint();
p.setAntiAlias(true); //去锯齿
p.setColor(Color.BLACK);
p.setStyle(Paint.Style.STROKE);
Canvas canvas = new Canvas(bitmap);  //bitmap就是我们原来的图,比如头像
p.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  //因为我们先画了图所以DST_IN
int radius = bitmap.getWidth; //假设图片是正方形的
canvas.drawCircle(radius, radius, radius, p); //r=radius, 圆心(r,r)

以上就是简单的示例,根据以上的16种模式你其实还可以做出更多效果。另外,只要你给一张相交图,那张图形状什么样,我们的图就可以显示成什么样。

通过裁剪画布区域实现指定形状的图形

Android中Canvas提供了ClipPath, ClipRect, ClipRegion 等方法来裁剪,通过Path, Rect ,Region 的不同组合,Android几乎可以支持任意形状的裁剪区域。因此,我们几乎可以获取任意形状的区域,然后在这个区域上画图,就可以获得,我们要的图片了,直接看示例。

int radius = src.getWidth() / 2; //src为我们要画上去的图,跟上一个示例中的bitmap一样。
Bitmap dest = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(dest);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
Path path = new Path();
path.addCircle(radius, radius, radius, Path.Direction.CW);
c.clipPath(path);   //裁剪区域
c.drawBitmap(src, 0, 0, paint);  //把图画上去

使用BitmapShader

直接先看示例
java
int radius = src.getWidth() / 2;
BitmapShader bitmapShader = new BitmapShader(src, Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
Bitmap dest = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(dest);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(bitmapShader);
c.drawCircle(radius,radius, radius, paint);

Shader就是画笔的渲染器,本质上这中方法其实是画圆,但是渲染采用了我们的图片,然后就可以获得指定的形状了。但是我觉得,这个不适合画很复杂的图形,但是在内存消耗上,应该比第一种小很多。同时呢,设置Shader.TileMode.MIRROR,还可以实现镜面效果,也是极好的。

上面就是实现的三种方法,三种方法都可以画很多的形状,当然遇到非常非常非常非常复杂的情况,我是建议使用第一种,这时候可以让美工给一张末班形状图,省自己去代码绘制了。大家根据自己的需求选择。

在github上面CustomShapeImageView就是用了我们所说的第一种方法绘制。RoundedImageViewCircleImageView则使用bitmapshader完成,当然可能还有一些其他的控件,也许还有其他的一些实现方法,如果你知道,可以回复告诉我^_^。

原文地址:http://isming.me/2014/09/19/draw-circle-image-in-android/,转载请注明出处。

常用有用的android adb命令

adb在开发中真的是时时都会用到,熟练使用可以帮助我们提高开发效率。前段时间看到一个外国程序员分享了一篇文章,觉得写的很好,介绍了一些很有意思的adb的命令,我就寻思着有空也写一篇,对于自己是一个总结,同时方便自己或者其他人以后查阅。

想要能够在命令行里面敲adb能够使用,先要保证你的adb所在的目录,一般是sdk/platform-tools目录,要在环境变量中,想要怎么配环境变量,自己google去。

首先要学会使用帮助,遇到不会用的命令可以直接敲adb 或者adb --help看帮助,帮助文档基本的命令都有。

adb devices 查看adb已经连接上的手机列表

adb install -r /path/to/apk 安装apk到手机, 带参数-r的话就卸载手机中已有的程序

adb uninstall package_name 卸载手机中的程序

adb push -p local remote 复制电脑中的文件到手机,-p显示进度

adb pull -p -a remote local 复制手机中的文件或者文件夹到电脑

adb shell 进入手机的shell命令行环境,可以进去后执行手机中支持的命令,也可以在本句之后加命令

adb shell pm uninstall package_name 卸载手机中的程序

adb shell pm install /path/of/apk/in/phone 安装手机sd卡中的程序

adb shell am start package_name/activity_in_package

adb shell am start package_name/activity_flly_qualified 启动activity

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png 截屏保存到screen.png

adb logcat 查看log

adb logcat -s TAG_NAME

adb logcat -s TAG_NAME_1 TAG_NAME_2

adb logcat ":PRIORITY" eg:adb logcat ":D"

adb logcat -s TAG_NAME:PRIORITY

adb logcat -c 清空log

ok。我能想到,和参考的别的文章上面,目前使用最多的一些命令就是这些了。更加详细的adb介绍,请参看谷歌官方文档.http://developer.android.com/tools/help/adb.html

PS:最新因为项目的需要,因此研究了一下滤镜,在gpuimage的基础上模仿instargram做了一套滤镜,放在github。上面了,欢迎取阅。https://github.com/sangmingming/android-instagram-filter

android推送技术方案与原理

推送服务现在广泛的使用,几乎成了每个app的必备,现在呢,苹果上面有APNs,android上面游GCM(中国不可用)。我也是经常使用第三方的推送,比如百度云推送,个推等等。但是一直想知道推送的原理,想着自己也能做出来,到网上搜到一些推送的方案(大段内容来自网上)。

方案一:使用GCM服务(Google Cloud Messaging)

简介:Google在Android上标配了自己的推送GCM(Google Cloud Messageing),可以帮助开发人员给他们的Android应用程序发送数据。它是一个轻量级的消息,告诉Android应用程序有新的数据要获取从服务器,或者它可能是一个消息,其中包含了4KB的payload data(像即时通讯这类应用程序可以直接使用该payload消息)。GCM服务处理排队的消息,并把消息传递到目标设备上运行的Android应用程序。

优点:Google提供的服务、原生、简单,无需实现和部署服务端。

缺点:

1.GCM要求Android系统必须是2.2以上的版本,所以对于不少2.2以前的系统没法推送

2.国内服务不稳定。而且不少国内的终端厂商纷纷把Google的服务去掉,替换上自己的。

3.需要用户绑定Google账号,但不少国内用户没有Google账号。

方案二:使用XMPP协议(Openfire + Spark + Smack)

简介:XMPP是一种基于XML的协议,它继承了在XML环境中灵活的发展性,有很强的可扩展性。包括上面讲的GCM服务器底层也是采用XMPP协议封装的。

优点:协议成熟、强大、可扩展性强、目前主要应用于许多聊天系统中,且已有开源的Java版的开发实例androidpn。

缺点:协议较复杂、冗余(基于XML)、费流量、费电,部署硬件成本高。

而androidpn(Android Push Notification)就是基于 XMPP 开源组件的一套整合方案,服务端基于Openfire、客户端基于Smack。到AndroidPN项目主页( http://sourceforge.net/projects/androidpn/ ) 下载2个文件: androidpn-server-0.5.0-bin.zip 和 androidpn-client-0.5.0.zip 分别是服务器和客户端的代码。详细的实现方式网上有不少文章。

androidpn有如下一些不足,开发的时候需要权衡:

1、androidpn服务端重启后客户端不会重连,这个非常悲剧

2、由于服务器不保存消息,造成了如果客户端当前离线就收不到消息。

3、androidpn发送完消息就不管了,所以没有消息回执报表之类,造成没法做应用后续的数据分析用户体验的改善,这对于企业级的应用是个致命伤。

XMPP协议比较费电费流量,这个对当前智能机的消耗太大,在窄带网络和不稳定的(手机)网络都不是最优的选择。但总体来说,XMPP协议还是比较成熟的。

方案三:使用MQTT协议(更多信息见: http://mqtt.org/)

简介:轻量级的、基于代理的“发布/订阅”模式的消息传输协议。

优点:协议简洁、小巧、可扩展性强、省流量、省电,目前已经应用到企业领域(参考: http://mqtt.org/software),且已有C++版的服务端组件rsmb。

缺点:不够成熟、实现较复杂、服务端组件rsmb不开源,部署硬件成本较高。

方案四:使用HTTP轮循方式

简介:定时向HTTP服务端接口(Web Service API)获取最新消息。

优点:实现简单、可控性强,部署硬件成本低。

缺点:实时性差。

方案五:采用第三方服务

目前有不少第三方提供了类似服务,客户端只需要嵌入第三方提供的lib库,由第三方建立长连接,负责消息的接收/发送。同时对于消息都有比较详细的报表数据,可以用于做数据分析挖掘和用户体验的改善。目前国内提供推送服务的有好几家,比较成熟的主要有百度云推送, 极光推送, 个推服务。

本文只是罗列现有的方案,文章内容大段来自网上,我希望有一天可以做出一个demo。