編輯:關於android開發
應用中的音樂一般放在res/raw目錄下
/** * 播放應用資源中的音樂 * * @param v */ public void player1(View v) { // 設置播放數據源 MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.gm); // 不需要准備,create,創建完成直接可以使用播放 mediaPlayer.start(); }
/** * 播放系統中的音樂 * * @param v */ public void player2(View v) { //文件地址 File file =new File(Environment.getExternalStorageDirectory(),"man.mp3"); //轉換為uri Uri uri = Uri.fromFile(file); // 設置播放數據源 MediaPlayer mediaPlayer = MediaPlayer.create(this,uri); // 不需要准備,create,創建完成直接可以使用播放 mediaPlayer.start(); }
以上兩個方法用起來非常方便,便這兩個方法每次都會返回新創建的Mediaplayer對象,同時也不方便控件播放狀態.如果需要播放多個音頻,使用這種方法就不方便.
可以使用MedaiPlayer.setDataSource()方法來裝載指定的音頻文件
播放
private MediaPlayer mediaPlayer ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mediaPlayer = new MediaPlayer(); } public void player(View v) { try { //初始化 mediaPlayer.reset(); //設置資源 mediaPlayer.setDataSource("/mnt/sdcard/man.mp3"); //准備聲音本地 mediaPlayer.prepare(); } catch (Exception e) { e.printStackTrace(); } //播放 mediaPlayer.start(); }
暫停與繼承播放
private void init(){ mediaPlayer = new MediaPlayer(); } public void player(View v) { try { init(); //初始化 mediaPlayer.reset(); //設置資源 mediaPlayer.setDataSource("/mnt/sdcard/man.mp3"); //准備聲音本地 mediaPlayer.prepare(); } catch (Exception e) { e.printStackTrace(); } //播放 mediaPlayer.start(); } /** * 暫停與繼承播放 * @param v */ public void pause(View v){ //判斷狀態 if(mediaPlayer!=null&&mediaPlayer.isPlaying()){ //暫停 mediaPlayer.pause(); }else if(mediaPlayer!=null) { mediaPlayer.start(); } } /** * 停止 * @param v */ public void stop(View v){ //判斷狀態 if(mediaPlayer!=null){ //停止播放資源 mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer=null; } }
private void init(){ mediaPlayer = new MediaPlayer(); } public void player(View v) { //本地Tomcat服務器的地址 String url="http://188.188.3.79:8080/itest/gm.mp3"; //播放,網絡音樂 try { init(); //初始化 http://188.188.3.79:8080/itest/gm.mp3 mediaPlayer.reset(); //設置資源 mediaPlayer.setDataSource(url); final ProgressDialog dialog = ProgressDialog.show(this, "加載中", "拼命加載中..........."); //准備聲音遠程音樂 mediaPlayer.prepareAsync(); /** * 設置監聽器什麼時候緩沖,准備好音樂, */ mediaPlayer.setOnPreparedListener(new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { //准備好了,就對話框消失 dialog.dismiss(); //開始播放 mediaPlayer.start(); } }); } catch (Exception e) { e.printStackTrace(); } }
添加權限
<uses-permission android:name="android.permission.INTERNET"/>
1,2,3只要調用它們的靜態方法create()方法創建相應的實例,
然後調用穹們的isAvailabel()方法判斷是否可用,
再調用setEnable(boolean enabled)方法啟用相應的效果即可
/* 定義系統回聲控制器 */ private void setAcousticEchoCanceler(){ mAcousticEchoCanceler = AcousticEchoCanceler.create(mPlayer.getAudioSessionId()); if(mAcousticEchoCanceler.isAvailable()){ //設置取消回聲功能 mAcousticEchoCanceler.setEnabled(true); } } /* 自動增益控制器 */ private void setAutomaticGainControl(){ mAutomaticGainControl = AutomaticGainControl.create(mPlayer.getAudioSessionId()); if(mAutomaticGainControl.isAvailable()){ //啟用自動增益功能 mAutomaticGainControl.setEnabled(true); } } /* 噪音壓制控制器 */ private void setNoiseSuppressor(){ mNoiseSuppressor = NoiseSuppressor.create(mPlayer.getAudioSessionId()); if(mNoiseSuppressor.isAvailable()){ //啟用噪音壓制功能 mNoiseSuppressor.setEnabled(true); } }
後面4個,者需要調用構造器來創建實例,同樣需要輸入一個audioSession參數,同樣用啟用它們需要調用 AudioEffect基類的setEnable(true)方法
如果應用程序經常需要播放密集,短促的音效,可以使用SoundPool來播放
為什麼不使用Mediaplayer?
缺點:
資源占用較高,延遲時間較長
不支持多個音頻同時播放
SoundPool主要用於播放一些較短的聲音片段,
與MediaPlayer相比,優勢在CPU資源占用低,反應延遲小
同時還支持設置聲音的品質,音量,播放比特率等參數
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/bomb" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="播放Bomb"/> <Button android:id="@+id/shot" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="播放Shot"/> <Button android:id="@+id/arrow" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="播放Arrow"/> </LinearLayout>
Activity
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button bomb; private Button shot; private Button arrow; //定義一個SoundPool private SoundPool soundPool; //定義一個Map用來存放聲音 private HashMap<Integer, Integer> soundMap = new HashMap<Integer, Integer>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bomb = (Button) findViewById(R.id.bomb); shot = (Button) findViewById(R.id.shot); arrow = (Button) findViewById(R.id.arrow); bomb.setOnClickListener(this); shot.setOnClickListener(this); arrow.setOnClickListener(this); AudioAttributes attr = new AudioAttributes.Builder() //設置音效使用的場景--游戲 .setUsage(AudioAttributes.USAGE_GAME) //設置音效的類型 .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); //創建聲音池 soundPool = new SoundPool.Builder() //設置聲明池的屬性 .setAudioAttributes(attr) //設置最大容量 .setMaxStreams(10) .build(); //加載指定音頻文件使用load方法 /* context the application context resId the resource ID priority the priority of the sound. Currently has no effect. Use a value of 1 for future compatibility. */ soundMap.put(1, soundPool.load(this, R.raw.bomb, 1)); soundMap.put(2, soundPool.load(this, R.raw.shot, 1)); soundMap.put(3, soundPool.load(this, R.raw.arrow, 1)); } /** * 單擊事件監聽 * * @param view */ @Override public void onClick(View view) { switch (view.getId()) { case R.id.bomb: /* soundID a soundID returned by the load() function leftVolume left volume value (range = 0.0 to 1.0) rightVolume right volume value (range = 0.0 to 1.0) priority stream priority (0 = lowest priority) loop loop mode (0 = no loop, -1 = loop forever) rate playback rate (1.0 = normal playback, range 0.5 to 2.0 */ soundPool.play(soundMap.get(1), 1, 1, 0, 0, 1); break; case R.id.shot: soundPool.play(soundMap.get(2), 1, 1, 0, 0, 1); break; case R.id.arrow: soundPool.play(soundMap.get(3), 1, 1, 0, 0, 1); break; } } }
在布局文件中定義VideoView就可以
<VideoView android:id="@+id/videoview" android:layout_width="match_parent" android:layout_height="match_parent"/>
在Activity在找到這個VideoView使用findViewById,設置資源開始播放
videoView.setVideoPath(); 或者videoView.setVideoURI();來設置資源 /* 找到這個控件 */ videoView = (VideoView) findViewById(R.id.videoview); videoView.setVideoPath("/mnt/sdcard/oppo.3gp"); //開始播放 videoView.start();
屏幕切換 繼續播放,不會重新開始
<activity android:name=".MainActivity" android:configChanges="orientation|keyboardHidden|screenSize">
使用VideoView播放不能做控制,暫停,停止之類的操作
聲明一個MediaController對象與ViewVideo對象 設置相互依賴 //定義控制器 MediaController mediaController = new MediaController(this);
/* 找到這個控件 */ videoView = (VideoView) findViewById(R.id.videoview); /* 設置相互依賴 */ mediaController.setAnchorView(videoView); videoView.setMediaController(mediaController); videoView.setVideoPath("/mnt/sdcard/oppo.3gp"); //開始播放 自動播放 //videoView.start(); //獲取焦點,要手動點擊播放才可以播放 videoView.requestFocus();
start與requestFocus()區別
MediaPlayer主要是用來播放音頻,因此它沒有提供圖像輸出界面此時就要使用SurfaceView來顯示MediaPlayer播放的圖像輸出
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:gravity="center_horizontal"> <ImageButton android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" /> <ImageButton android:id="@+id/pause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pause" /> <ImageButton android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/stop" /> </LinearLayout> </RelativeLayout>
Actvity
/** * 使用MediaPlayer與SurfaceView播放視頻 */ public class MainActivity extends AppCompatActivity implements View.OnClickListener { private MediaPlayer mediaPlayer; private SurfaceView surfaceView; private ImageButton play; private ImageButton pause; private ImageButton stop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* 初始化 */ mediaPlayer = new MediaPlayer(); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); play = (ImageButton) findViewById(R.id.play); pause = (ImageButton) findViewById(R.id.pause); stop = (ImageButton) findViewById(R.id.stop); play.setOnClickListener(this); pause.setOnClickListener(this); stop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.pause: pause(); break; case R.id.play: play(); break; case R.id.stop: stop(); break; } } /** * 播放 */ private void play() { File file = new File(Environment.getExternalStorageDirectory(), "bb.mp4"); Uri uri = Uri.fromFile(file); mediaPlayer.reset(); try { mediaPlayer.setDataSource(this, uri); mediaPlayer.prepare(); //設置視頻輸出到SurfaceView mediaPlayer.setDisplay(surfaceView.getHolder()); //獲取窗口管理器 WindowManager manager = getWindowManager(); //獲取屏幕大小 DisplayMetrics metrics = new DisplayMetrics(); manager.getDefaultDisplay().getMetrics(metrics); //設置視頻保持縱橫比例縮放占滿 整個屏幕 surfaceView.setLayoutParams(new RelativeLayout.LayoutParams(metrics.widthPixels, mediaPlayer.getVideoHeight() * metrics.widthPixels / mediaPlayer.getVideoHeight())); } catch (IOException e) { e.printStackTrace(); } mediaPlayer.start(); } /** * 暫停 */ private void pause() { if(mediaPlayer.isPlaying()){ mediaPlayer.pause(); }else { mediaPlayer.start(); } } /** * 停止 */ private void stop() { if(mediaPlayer!=null){ mediaPlayer.stop(); mediaPlayer.release(); } } /** * 監聽器 */ private class SurfaceListener implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { play(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } } @Override protected void onDestroy() { super.onDestroy(); if(mediaPlayer!=null){ mediaPlayer.stop(); mediaPlayer.release(); mediaPlayer=null; } } }
API
Create a new instance of android.media.MediaRecorder. Set the audio source using MediaRecorder.setAudioSource(). You will probably want to use MediaRecorder.AudioSource.MIC. Set output file format using MediaRecorder.setOutputFormat(). Set output file name using MediaRecorder.setOutputFile(). Set the audio encoder using MediaRecorder.setAudioEncoder(). Call MediaRecorder.prepare() on the MediaRecorder instance. To start audio capture, call MediaRecorder.start(). To stop audio capture, call MediaRecorder.stop(). When you are done with the MediaRecorder instance, call MediaRecorder.release() on it. Calling MediaRecorder.release() is always recommended to free the resource immediately.解釋
布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="horizontal"> <ImageButton android:id="@+id/record" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/record" /> <ImageButton android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/stop" /> </LinearLayout>
Activity
/** * MediaRecord * */ public class MainActivity extends Activity implements View.OnClickListener { private static final String TAG ="MainActivity" ; private ImageButton record; private ImageButton stop; private File soundFile; private MediaRecorder mRecorder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); record = (ImageButton) findViewById(R.id.record); stop = (ImageButton) findViewById(R.id.stop); /** * 為2個按鍵設置單擊事件綁定監聽器 */ record.setOnClickListener(this); stop.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.record: record(); break; case R.id.stop: stop(); break; } } /** * 錄制音頻 */ private void record(){ /** * 判斷SD卡是否已經掛載成功 */ if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ Toast.makeText(MainActivity.this, "SD卡未成功掛載,請插入SD卡", Toast.LENGTH_SHORT).show(); return; } try { //創建要錄制的文件 soundFile = new File(Environment.getExternalStorageDirectory(),+System.currentTimeMillis()+".amr"); Log.d(TAG,Environment.getExternalStorageDirectory()+""); Log.d(TAG,soundFile.getAbsolutePath()); //創建錄制 mRecorder = new MediaRecorder(); //設置聲音來源MIC mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設置輸出格式 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //設置輸出文件 mRecorder.setOutputFile(soundFile.getPath()); //設置編碼 mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); //准備錄制 mRecorder.prepare(); //錄制 mRecorder.start(); } catch (IOException e) { e.printStackTrace(); } } /** * 停止錄制音頻, */ private void stop(){ if(soundFile!=null&&soundFile.exists()){ mRecorder.stop(); mRecorder.release(); mRecorder=null; } } @Override protected void onDestroy() { super.onDestroy(); if(soundFile!=null&&soundFile.exists()){ mRecorder.stop(); mRecorder.release(); mRecorder=null; } } }
權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
Android5.0對象拍照的API進行了全新的設計,新增了Camera V2 API,,大幅提高了拍照功能,還能支持RAW照片的輸,還可以允許調整相機的對焦,曝光,快門等.這裡只是簡單調用
布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:onClick="capture" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="使用攝像頭"/> <ImageView android:id="@+id/iv_display" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
Activity
/** 使用系統的相機進行拍照,並顯示在界面上 */ public class MainActivity extends AppCompatActivity { private ImageView display; private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private Uri fileUri; private File file; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); display = (ImageView) findViewById(R.id.iv_display); } /** * 調用攝像頭 * @param v */ public void capture(View v){ // 使用Intent的方式去打開系統相機應用 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg"); fileUri =Uri.fromFile(file); // 設置保存文件 intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // 啟動一個Activity為了拿到結果 startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //data這裡是NUll不能進行判斷 if(requestCode==CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE){ // if(resultCode==RESULT_OK){ Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); display.setImageBitmap(bitmap); }else{ Toast.makeText(MainActivity.this, "失敗", Toast.LENGTH_SHORT).show(); } } } }
權限
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
與上面的步驟一樣.只是改一個Intent的Action,保存文件的文件後綴 顯示的話可以使用VideoView,或者SurfaceView 簡單一點就使用VideoView
布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:onClick="record" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="錄像"/> <VideoView android:id="@+id/videoview" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
Activtity
/** * 使用攝像機錄像 */ public class MainActivity extends AppCompatActivity { private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; private VideoView videoView; private File file; /* VideoView與mediaocontroller控制器 */ private MediaController mediaController; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); videoView = (VideoView) findViewById(R.id.videoview); } /** 開始錄像 */ public void record(View v){ //調用攝像頭的錄像功能 Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); //保存的文件 file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".mp4"); Uri fileUri =Uri.fromFile(file); //保存數據 intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri); //啟用一個系統的相機 startActivityForResult(intent,CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE); } /** * 接收結果 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //data沒有數據是NULL if(requestCode==CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE){ //說明成功 if(resultCode==RESULT_OK){ //再次判斷 下文件是否保存成功 if(file.exists()){ mediaController = new MediaController(this); videoView.setVideoPath(file.getAbsolutePath()); mediaController.setAnchorView(videoView); videoView.setMediaController(mediaController); //獲取焦點 或者直接播放 .start() videoView.requestFocus(); }else{ Toast.makeText(MainActivity.this, "保存失敗", Toast.LENGTH_SHORT).show(); } }else{ Toast.makeText(MainActivity.this, "失敗", Toast.LENGTH_SHORT).show(); } } } }
權限
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
使用MediaProjectionManager
/** * 捕捉屏幕 */ public class MainActivity extends AppCompatActivity { private static final int CAPTURE_CODE = 100; private SurfaceView surfaceView; private int screenDensity; private Surface surface; //顯示區域的寬高 private int displayWidth = 400; private int displayHeight = 700; private boolean screenSharing; private MediaProjection mediaProjection; private MediaProjectionManager mediaProjectionManager; private VirtualDisplay virtualDisplay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceView = (SurfaceView) findViewById(R.id.surface); surface = surfaceView.getHolder().getSurface(); // 獲取屏幕分辨率 DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); //獲取屏幕密度 screenDensity = metrics.densityDpi; // 控制界面上的SurfaceView組件的寬度和高度 ViewGroup.LayoutParams lp = surfaceView.getLayoutParams(); lp.width = displayWidth; lp.height = displayHeight; // 獲取MediaProjectionManager管理器 mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); } /** * 捕捉屏幕 當用戶單擊開關按鈕時激發該方法 * * @param view 開關 */ public void onToggleScreenShare(View view) { if (((ToggleButton) view).isChecked()) { shareScreen(); } else { stopScreen(); } } /** * 停止共享 */ private void stopScreen() { screenSharing = false; if (virtualDisplay == null) { return; } virtualDisplay.release(); } /** * 共享屏幕 */ private void shareScreen() { screenSharing = true; if (surface == null) { return; } if (mediaProjection == null) { //建立一個屏幕捕捉的意圖 Intent intent = mediaProjectionManager.createScreenCaptureIntent(); startActivityForResult(intent, CAPTURE_CODE); return; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAPTURE_CODE) { // 如果resultCode不等於RESULT_OK,表明用戶拒絕了屏幕捕捉 if (resultCode != RESULT_OK) { Toast.makeText(this, "用戶取消了屏幕捕捉" , Toast.LENGTH_SHORT).show(); return; } mediaProjection = mediaProjectionManager.getMediaProjection(resultCode,data); /* public android.hardware.display.VirtualDisplay createVirtualDisplay(java.lang.String name, int width, int height, int dpi, int flags, android.view.Surface surface, android.hardware.display.VirtualDisplay.Callback callback, android.os.Handler handler) */ virtualDisplay = mediaProjection.createVirtualDisplay("屏幕捕捉",displayWidth,displayHeight,screenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,surface,null,null); } } @Override protected void onDestroy() { super.onDestroy(); if (mediaProjection != null) { mediaProjection.stop(); mediaProjection = null; } } }
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <SurfaceView android:layout_centerInParent="true" android:id="@+id/surfaceview" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
Activity
/** * Surface畫圓 */ public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private SurfaceView surfaceview; private DisplayMetrics metrics; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); surfaceview= (SurfaceView) findViewById(R.id.surfaceview); surfaceview.getHolder().addCallback(new MySureFaceHolad()); metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); } private class MySureFaceHolad implements SurfaceHolder.Callback{ @Override public void surfaceCreated(SurfaceHolder holder) { Log.d(TAG,"surfaceCreated"); new Thread(){ @Override public void run() { int radus = 5; SurfaceHolder holder1 = surfaceview.getHolder(); for (int i = 0; i < 300; i++) { Canvas canvas = holder1.lockCanvas(); canvas.drawColor(Color.WHITE); Paint paint = new Paint(); paint.setColor(Color.RED); canvas.drawCircle(metrics.widthPixels / 2, metrics.heightPixels / 2, radus + i, paint); holder1.unlockCanvasAndPost(canvas); SystemClock.sleep(20); } } }.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG,"surfaceChanged"); } @Override public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "surfaceDestroyed"); } } }
Android 主頁面頂部欄的通知Notification ,可以自定義通知消息欄的風格,並且點擊通知欄進人本程序。,android自定義消息欄常用的程序通知,顯示到主頁
Android事件分發機制總結 理解事件的分發機制,需要對View和ViewGroup事件的分發分別探討。View和ViewGroup的區別,一個View控件是指它裡面不
android開發環境以及genymotion虛擬機配合HBuilder測試(自總結),genymotionhbuilder一、安裝android-studio http
AndroidStudio 1.4升級到1.5後,peer not authenticated錯誤 解決方法: 找到項目最外層的build.gradle文件,將其中的