編輯:關於Android編程
單色圖:每個像素占用1/8個字節圖片大小 = 圖片的總像素 * 每個像素占用的大小
Android系統以ARGB表示每個像素,所以每個像素占用4個字節,很容易內存溢出
獲取手機屏幕寬高(分辨率)
Display dp = getWindowManager().getDefaultDisplay();
int screenWidth = dp.getWidth();
int screenHeight = dp.getHeight();
獲取圖片寬高(分辨率)
Options opts = new Options();//創建一個位圖工廠的配置參數
//請求圖片屬性但不申請內存,解碼器不去真正的解析位圖,但是還能獲取圖片的寬高信息
由於是在Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opts);程序崩掉的,當設置了opts.inJustDecodeBounds = true;之後,bm就返回null,不會崩掉。這個時候再去對圖片做屏幕適配就可以了。
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile("sdcard/dog.jpg", opts);//返回null了,不用設置變量值
int imageWidth = opts.outWidth;//獲取圖片的寬
int imageHeight = opts.outHeight;//獲取圖片的高
圖片的寬高除以屏幕寬高,算出寬和高的縮放比例,取較大值作為圖片的縮放比例
int scale = 1;
int scaleX = imageWidth / screenWidth;//圖片寬/屏幕寬
int scaleY = imageHeight / screenHeight;//圖片高/屏幕高
if(scaleX >= scaleY && scaleX > 1){
scale = scaleX;//獲取大的縮放比,作為圖片的最終縮放比例
}
else if(scaleY > scaleX && scaleY > 1){
scale = scaleY;
}
按縮放比例加載圖片
//設置縮放比例
opts.inSampleSize = scale;
//這個時候有了縮放比了。因此要再一次為圖片申請內存,使用BitmapFactory去解析位圖
opts.inJustDecodeBounds = false;//真正的解析位圖
Bitmap bm = BitmapFactory.decodeFile("sdcard/dog.jpg", opts);
iv.setImageBitmap(bm);//把bitmap顯示在iv上
直接加載的bitmap對象是只讀的,無法修改,要修改圖片只能在內存中創建出一個一模一樣的bitmap副本,然後修改副本
//加載原圖
Bitmap srcBm = BitmapFactory.decodeFile("sdcard/photo3.jpg");
iv_src.setImageBitmap(srcBm);
//創建與原圖大小一致的空白bitmap
Bitmap copyBm = Bitmap.createBitmap(srcBm.getWidth(), srcBm.getHeight(), srcBm.getConfig());
//定義畫筆
Paint paint = new Paint();
//把紙鋪在畫版上
Canvas canvas = new Canvas(copyBm);
//把srcBm的內容繪制在copyBm上
canvas.drawBitmap(srcBm, new Matrix(), paint);
iv_copy.setImageBitmap(copyBm);
首先定義一個矩陣對象
Matrix mt = new Matrix();
縮放效果
//x軸縮放1倍,y軸縮放0.5倍
mt.setScale(1, 0.5f);
旋轉效果
//以copyBm.getWidth() / 2, copyBm.getHeight() / 2點為軸點,順時旋轉30度
mt.setRotate(30, copyBm.getWidth() / 2, copyBm.getHeight() / 2);
平移
//x軸坐標+10,y軸坐標+20
mt.setTranslate(10, 20);
鏡面
//把X坐標都變成負數
mt.setScale(-1, 1);
//圖片整體向右移
mt.postTranslate(copyBm.getWidth(), 0);
倒影
//把Y坐標都變成負數
mt.setScale(1, -1);
//圖片整體向下移
mt.postTranslate(0, copyBm.getHeight());
記錄用戶觸摸事件的XY坐標,繪制直線 * 給ImageView設置觸摸偵聽,得到用戶的觸摸事件,並獲知用戶觸摸ImageView的坐標
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
//觸摸屏幕
case MotionEvent.ACTION_DOWN:
//得到觸摸屏幕時手指的坐標
startX = (int) event.getX();
startY = (int) event.getY();
break;
//在屏幕上滑動
case MotionEvent.ACTION_MOVE:
//用戶滑動手指,坐標不斷的改變,獲取最新坐標
int newX = (int) event.getX();
int newY = (int) event.getY();
//用上次onTouch方法得到的坐標和本次得到的坐標繪制直線
canvas.drawLine(startX, startY, newX, newY, paint);
iv.setImageBitmap(copyBm);
startX = newX;
startY = newY;
break;
}
return true;
}
});
刷子效果,加粗畫筆
paint.setStrokeWidth(8);
調色板,改變畫筆顏色
paint.setColor(Color.GREEN);
保存圖片至SD卡
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("sdcard/dazuo.png"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//保存圖片
copyBm.compress(CompressFormat.PNG, 100, fos);
系統每次收到SD卡就緒廣播時,都會去遍歷sd卡的所有文件和文件夾,把遍歷到的所有多媒體文件都在MediaStore數據庫保存一個索引,這個索引包含多媒體文件的文件名、路徑、大小
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
sendBroadcast(intent);
服務裡定義play、stop、pause、continuePlay等方法
private void play() {
// TODO Auto-generated method stub
player.reset();
try {
player.setDataSource("sdcard/bzj.mp3");
player.prepare();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.start();
}
private void pause() {
player.pause();
}
private void stop() {
player.stop();
}
private void continuePlay() {
player.start();
}
把這幾個方法抽取成一個接口MusicInterface先start啟動MusicService,再bind
Intent intent = new Intent(this, MusicService.class);
startService(intent);
bindService(intent, conn, BIND_AUTO_CREATE);
獲取當前的播放時間和當前音頻的最長時間
int currentPosition = player.getCurrentPosition();
int duration = player.getDuration();
播放進度需要不停的獲取,不停的刷新進度條,使用計時器每500毫秒獲取一次播放進度發消息至Handler,把播放進度放進Message對象中,在Handler中更新SeekBar的進度
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
int currentPosition = player.getCurrentPosition();
int duration = player.getDuration();
Message msg = Message.obtain();
//把播放進度存入Message中
Bundle data = new Bundle();
data.putInt("currentPosition", currentPosition);
data.putInt("duration", duration);
msg.setData(data);
MainActivity.handler.sendMessage(msg);
}
}, 5, 500);
在Activity中定義Handler
static Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
//取出消息攜帶的數據
Bundle data = msg.getData();
int currentPosition = data.getInt("currentPosition");
int duration = data.getInt("duration");
//設置播放進度
sb.setMax(duration);
sb.setProgress(currentPosition);
};
};
//給sb設置一個拖動偵聽
sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//停止拖動時調用
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
int progress = seekBar.getProgress();
mi.seekTo(progress);
}
//開始拖動時調用
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
//拖動的時候不斷調用
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
});
就是實現在頂部這樣的搜索框。 一、這個搜索框是actionbar上的menu上的一個item.叫SearchView.我們可以先在menu選項裡定義好:
新建一個Android工程。 一 布局 先看效果圖: 打開main.xml修改內容如下:
寫作原因:跨進程通信的實現和理解是Android進階中重要的一環。下面博主分享IPC一些相關知識、操作及自己在學習IPC過程中的一些理解。這一章使用Messenger實現
前面分析了電話撥號界面及電話呼叫界面,由於Android的電話Phone設計的很復雜,因此先從UI層入手分析。想要了解Android的電話撥號UI,請查看Android電