本文章来给大家介绍Android中Bitmap和Drawable用法详解,有需要了解的同学可进入参考。
一、相关概念
1、Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable),我们根据画图的需求,创建相应的可画对象2、Canvas画布,绘图的目的区域,用于绘图3、Bitmap位图,用于图的处理4、Matrix矩阵二、Bitmap
1、从资源中获取Bitmap
Resources res = getResources();
Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.icon);
2、Bitmap → byte[]
代码如下 |
复制代码 |
public byte[] Bitmap2Bytes(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
|
3、byte[] → Bitmap
代码如下 |
复制代码 |
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
|
Bitmap缩放
代码如下 |
复制代码 |
public static Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
float scaleWidth = ((float) width / w);
float scaleHeight = ((float) height / h);
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
return newbmp;
}
|
5、将Drawable转化为Bitmap
代码如下 |
复制代码 |
public static Bitmap drawableToBitmap(Drawable drawable) {
// 取 drawable 的长宽
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
// 取 drawable 的颜色格式
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
// 建立对应 bitmap
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
// 建立对应 bitmap 的画布
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
// 把 drawable 内容画到画布中
drawable.draw(canvas);
return bitmap;
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Bitmap output = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, w, h);
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
|
6、获得圆角图片
代码如下 |
复制代码 |
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
final int reflectionGap = 4;
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Matrix matrix = new Matrix();
matrix.preScale(1, -1);
Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w,
h / 2, matrix, false);
Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2),
Config.ARGB_8888);
Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(bitmap, 0, 0, null);
Paint deafalutPaint = new Paint();
canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint);
canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, h, w, bitmapWithReflection.getHeight()
+ reflectionGap, paint);
return bitmapWithReflection;
}
|
三、Drawable
代码如下 |
复制代码 |
Bitmap bm=xxx; //xxx根据你的情况获取
BitmapDrawable bd= new BitmapDrawable(getResource(), bm);
因为BtimapDrawable是Drawable的子类,最终直接使用bd对象即可。
|
2、Drawable缩放
代码如下 |
复制代码 |
public static Drawable zoomDrawable(Drawable drawable, int w, int h) {
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
// drawable转换成bitmap
Bitmap oldbmp = drawableToBitmap(drawable);
// 创建操作图片用的Matrix对象
Matrix matrix = new Matrix();
// 计算缩放比例
float sx = ((float) w / width);
float sy = ((float) h / height);
// 设置缩放比例
matrix.postScale(sx, sy);
// 建立新的bitmap,其内容是对原bitmap的缩放后的图
Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,
matrix, true);
return new BitmapDrawable(newbmp);
}
|
在Android中要让一个程序的界面始终保持一个方向,不随手机方向转动而变化的办法: 只要在AndroidManifest.xml里面配置一下就可以了,小编来给大家介绍一款Android禁止横屏竖屏切换程序代码,有需要了解的同学可参考
在AndroidManifest.xml的activity(需要禁止转向的activity)配置中加入android:screenOrientation="landscape"属性即可(landscape是横向,portrait是竖屏)。例如:
代码如下 |
复制代码 |
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ray.linkit"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main"
android:label="@string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".GamePlay"
android:screenOrientation="portrait"></activity>
<activity android:name=".OptionView"
android:screenOrientation="portrait"></activity>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
|
另外,android中每次屏幕方向切换时都会重启Activity,所以应该在Activity销毁前保存当前活动的状态,在Activity再次Create的时候载入配置,那样,进行中的游戏就不会自动重启了!
要避免在转屏时重启activity,可以通过在androidmanifest.xml文件中重新定义方向(给每个activity加上android:configChanges=”keyboardHidden|orientation”属性),并根据Activity的重写onConfigurationChanged(Configuration newConfig)方法来控制,这样在转屏时就不会重启activity了,而是会去调用onConfigurationChanged(Configuration newConfig)这个回调方法。例如
代码如下 |
复制代码 |
if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
//横屏
setContentView(R.layout.file_list_landscape);
}else{
//竖屏
setContentView(R.layout.file_list);
}
|
需要注意的是如果你的横竖屏布局不一样,那么使用onConfigurationChanged会导致切换之后布局没有变化,所以该设置慎用为好。
.
本文章来给大家介绍Android RelativeLayout 属性用法详解,有需要了解RelativeLayout 属性的同学可进入参考参考。
// 相对于给定ID控件
代码如下 |
复制代码 |
android:layout_above 将该控件的底部置于给定ID的控件之上;
android:layout_below 将该控件的底部置于给定ID的控件之下;
android:layout_toLeftOf 将该控件的右边缘与给定ID的控件左边缘对齐;
android:layout_toRightOf 将该控件的左边缘与给定ID的控件右边缘对齐;
android:layout_alignBaseline 将该控件的baseline与给定ID的baseline对齐;
android:layout_alignTop 将该控件的顶部边缘与给定ID的顶部边缘对齐;
android:layout_alignBottom 将该控件的底部边缘与给定ID的底部边缘对齐;
android:layout_alignLeft 将该控件的左边缘与给定ID的左边缘对齐;
android:layout_alignRight 将该控件的右边缘与给定ID的右边缘对齐;
// 相对于父组件
android:layout_alignParentTop 如果为true,将该控件的顶部与其父控件的顶部对齐;
android:layout_alignParentBottom 如果为true,将该控件的底部与其父控件的底部对齐;
android:layout_alignParentLeft 如果为true,将该控件的左部与其父控件的左部对齐;
android:layout_alignParentRight 如果为true,将该控件的右部与其父控件的右部对齐;
// 居中
android:layout_centerHorizontal 如果为true,将该控件的置于水平居中;
android:layout_centerVertical 如果为true,将该控件的置于垂直居中;
android:layout_centerInParent 如果为true,将该控件的置于父控件的中央;
// 外部间隔
android:layout_marginTop 上偏移的值;
android:layout_marginBottom 下偏移的值;
android:layout_marginLeft 左偏移的值;
android:layout_marginRight 右偏移的值;
|
RelativeLayout代码
代码如下 |
复制代码 |
RelativeLayout relativeLayout = new RelativeLayout(context);
Spinner spinner = new Spinner(context);
edit_text_add_country = new AutoCompleteTextView(context);
edit_text_add_stock = new EditText(this);
RadioGroup containCountry = new RadioGroup(context);
spinner.setId(1);
edit_text_add_country.setId(2);
edit_text_add_stock.setId(3);
containCountry.setId(4);
String[] mCountries = { "China" , "USA", "China2", "Comunicate"};
List<String> allcountries = new ArrayList<String>();
ArrayAdapter<String> aspnCountries;
for (int i = 0; i < mCountries.length; i++) {
allcountries.add(mCountries[i]);
}
aspnCountries = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, allcountries);
aspnCountries
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(aspnCountries);
edit_text_add_country.setAdapter(aspnCountries);
edit_text_add_country.setHint("input country name");
edit_text_add_stock.setHint("input stock name");
RelativeLayout.LayoutParams param1, param2, param3;
param1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
param2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
param2.addRule(RelativeLayout.BELOW, 1);
param3 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
param3.addRule(RelativeLayout.BELOW, 4);
ViewGroup.LayoutParams param4, param5;
param4 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
param5 = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
containCountry.addView(spinner,param4);
containCountry.addView(edit_text_add_country, param5);
relativeLayout.addView(containCountry, param1);
relativeLayout.addView(edit_text_add_stock, param3);
builder.setView(relativeLayout);
|
看个实例
RelativeLayout代码实现及点击设置
代码如下 |
复制代码 |
public class Main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ArrayList<Person> personList = new ArrayList<Person>();
personList.add(new Person("zwx","23"));
personList.add(new Person("zwx1","24"));
personList.add(new Person("zwx2","25"));
LinearLayout ll = (LinearLayout)findViewById(R.id.LinearLayout01);
for(Person person : personList){
RelativeLayout rl = new RelativeLayout(this);
RelativeLayout.LayoutParams rll = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
rl.setLayoutParams(rll);
TextView tv1 = new TextView(this);
RelativeLayout.LayoutParams tv1_rl = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
tv1_rl.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
tv1.setText(person.getName());
rl.addView(tv1, tv1_rl);
TextView tv2 = new TextView(this);
RelativeLayout.LayoutParams tv2_rl = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
tv2_rl.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
tv2.setText(person.getAge());
rl.addView(tv2, tv2_rl);
ll.addView(rl);
rl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(Main.this, "11", 5000).show();
}
}) ;
}
}
}
|
注意:不能在RelativeLayout容器本身和他的子元素之间产生循环依赖,比如说,不能将RelativeLayout的高设置成为WRAP_CONTENT的时候将子元素的高设置成为ALIGN_PARENT_BOTTOM。
Android中使用ant混淆编译方法有需要的同学可参考参考。
1.拿一个普通项目来说,首先为它加上ant编译功能。
代码如下 |
复制代码 |
android update project --name project_name -t 3 -p D:/temp/project_name
|
此时会在项目根目录自动生成一个名为build.xml的ant脚本。上面的project_name是你的项目名称。
2.加入混淆功能
就第一步来说,在命令行中已经可以使用ant进行编译了。因为Android中是这样的,在输入命令ant debug的时候会自动调用D:/android-sdk-windows/tools/ant/main_rules.xml目录下的规则文件,所以无需自己写ant脚本了。既然它会调用默认的规则文件(默认文件没有加入混淆功能),那么我们想要混淆,直接在这个规则文件上修改就好了。在名为-dex的target后加入一个target,代码如下:
代码如下 |
复制代码 |
1 <target name="optimize" depends="compile"> <jar basedir="${out.classes.absolute.dir}" destfile="temp.jar"> <java jar="D:/android-sdk-windows/tools/proguard/lib/proguard.jar" fork="true" failonerror="true"><jvmarg value="-Dmaximum.inlined.code.length=32"> <arg value="-injars temp.jar"><arg value="-outjars optimized.jar"><arg value="-libraryjars '${android.jar}'"><!-- value="-libraryjars ${library-jar}/some_lib_used.jar"> --><arg value="-dontpreverify"><arg value="-dontoptimize"><arg value="-dontusemixedcaseclassnames"><arg value="-repackageclasses"><arg value="-allowaccessmodification"> <arg value="-keep public class * extends android.app.Activity"> <arg value="-keep public class * extends android.app.Service"> <arg value="-keep public class * extends android.content.BroadcastReceiver"> <arg value="-keep public class * extends android.content.ContentProvider"> <arg value="-keep public class * extends android.view.View"> <arg value="-optimizationpasses 1"> <arg value="-verbose"><arg value="-dontskipnonpubliclibraryclasses"><arg value="-dontskipnonpubliclibraryclassmembers"><arg value="-ignorewarning"> </arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></arg></!--></arg></arg></arg></jvmarg></java> <delete file="temp.jar"> <delete dir="${out.classes.absolute.dir}"> <mkdir dir="${out.classes.absolute.dir}"> <unzip" width=100% src="optimized.jar" mce_src="optimized.jar" dest="${out.classes.absolute.dir}"> <delete file="optimized.jar"></delete></unzip></mkdir></delete></delete></jar></target>
|
修改上面代码涉及到路径的地方,改成本地对应的路径。<arg value="-ignorewarning"/>这一行是自己加入的,意思是忽略警告。
接着在名为-dex的target中进行一个混淆依赖,加入后代码如下:
代码如下 |
复制代码 |
1 <target name="-dex" depends="compile, optimize, -post-compile, -obfuscate" unless="do.not.compile"> <if condition="${manifest.hasCode}"> <then> <dex-helper> </dex-helper></then> <else> <echo>hasCode = false. Skipping...</echo> </else> </if></target>
|
实际上加入的只是optimize,意思是这个target依赖target optimize。
3.开始编译
可以在命令行中编译了,编译后把class.dex进行反编译,可以看出来混淆成功。不知道为什么在我们的项目中反编译不回来,但是可以保证混淆是成功了。我拿过其他例子项目编译后反编译过,可以看下图:(不好意思,注册一星期之内不能上传图片)
本文章来给大家介绍android检测包名和类名是否存在的方法,有需要了解的同学可进入参考参考。
1.对包名的判断,异常则说明不存在:
代码如下 |
复制代码 |
try {
PackageManager pm = getPackageManager();
pm.getPackageInfo("com.org", PackageManager.GET_ACTIVITIES);
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
|
2.对类名的判断,异常则说明不存在:
代码如下 |
复制代码 |
try {
Class.forName("com.org.MainActivity");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
return;
}
|
标签:[!--infotagslink--]