本文已参加「新人创作礼」活动,一起开启掘金创作之路
- android studio的配置
- 类
- view: 位于android.view包中 View的子类位于android.widget包中
- 属性
- id
- background
- padding 内边距 上下左右
- 属性
- viewGroup 控制view如何拜访
- layoutParams
- layout_height match_pa rent 与容器相同 wrap_content与内容为主
- layout_width
- marginLayoutParams 外边距
- layout_marginTop
- layout_marginBottom
- layout_marginStart
- layout_marginEnd
- layoutParams
- view: 位于android.view包中 View的子类位于android.widget包中
- 布局管理器
- 相对布局管理器RelativeLayout
- 布局管理器属性
- gravity子组件摆放
- ignoregravity:[组件id] 无视
- 子组件属性
- layout_above[组件id] 组件相对于参考位置
- layout_alignParentBottom [bool] 组件相对于父容器
- layout_alingnBottom [组件id] 组件相对于参考位置的边界
- layout_centerHorizontal 位于布局管理器的位置
- 布局管理器属性
- 线性布局管理器LinearLayout
- 布局管理器的属性
- orientation
- vertical 垂直
- horizontal 水平
- gravity 显示效果 center,right|bottom
- orientation
- 组件属性
- layout_weight:
- 布局管理器的属性
- 帧布局管理器FrameLayout
- 布局管理器的属性
- foreground 最前端图片
- foregroundGravity前端图片位置
- 布局管理器的属性
- 表格布局管理器TableLayout [可跨列]
- 布局管理器的属性
- TableRow 行
- collapseColumns 隐藏列
- stretchColumns 允许被拉伸
- shrinkColumns 允许被收缩
- 布局管理器的属性
- 网格布局管理器GridLayout [可跨行列]
- 布局管理器的属性
- columnCount 列数
- orientation 水平或垂直排列
- rowCount 行数
- 组件属性
- layout_column 指定位于第几列
- layout_columnSpan 指定横向跨几列
- layout_columnWeight 水平方向权重
- layout_gravity 方式
- layout_row 指定位于第几行
- layout_rowSpan 指定跨几行
- layout_rowWeight 指定垂直方向权重
- 布局管理器的属性
- 相对布局管理器RelativeLayout
- 组件
- 文本框组件textView
- text [string values]
- textSize [sp]
- textColor
- singleLine 单行文本框
- 编辑框组件EditText
- hint 提示文本
- inputType 输入类型 [textMutline]
- drawableLeft/drawableStart/drawableEnd/drawableBottom/drawablePadding
- lines
- getText()获取编辑框内容
- 按钮Button
- Text 内容
- 监听器
- 匿名内部类
- xml中指定
- 图片按钮 ImageButton
- 单选框radioButton
- radioGroup 遍历getChildAt 获取单个radioButton
- radioGroup onCheckedChangeListener checkedId-->radioButton
- 复选框checkBox
- 时间dataPicker
- init() 初始化
- onDataChange 事件
- TimePicker时钟
- 计时器Chronometer
- setBase 设置起始时间
- setFormat 设置显示时间格式
- start 指定开始计时
- stop 指定停止计时
- onChrometerTick
- 进度条progressBar
- style
- style="?android:attr/progressBarStyleHorizontal"
- style="@android:style/Widget.ProgressBar.Horizontal
- style="@android:style/Widget.ProgressBar.Inverse
- max 最大值
- progress 当前值
- style
- 拖动条SeekBar
- 星级评分条
- numstarts 星星总数
- rating 点亮个数
- stepSize
- isIndicator 是否不可更改
- 图像视图 ImageView
- scaleType
- center 保持图像大小 以ImageView为中心 图像大截取
- centerInside 原图大按照比例缩放 原图小 居中显示
- centerCrop 原图大按比例缩放 原图小 按宽高比例放大
- matrix 原图大小显示在左上角
- fitXy 填充
- fitStart 以ImageView的高度放大缩小 显示在上方
- fitCenter 以ImageView的高度放大缩小 显示在中间
- fitEnd 以ImageView的高度放大缩小 显示在下方
- adjustViewBounds 是否调整
- maxHeight
- maxWidth
- scaleType
- GridView视图管理器
- numColumn 几列
- columnWidth 每列宽度
- verticalSpace 横向空隙
- Adapter 适配器
- BaseAdapter
public class ImageAdapter extends BaseAdapter { private Context imageContext; public ImageAdapter(Context c) { imageContext = c; } @Override public int getCount() { return imageResource.length; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ImageView imageView; if (convertView == null) { imageView = new ImageView(imageContext); imageView.setLayoutParams(new GridView.LayoutParams(300, 150)); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } else { imageView = (ImageView) convertView; } imageView.setImageResource(imageResource[position]); return imageView; } } - SimpleAdapter
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); for (int i = 0; i < imageResource.length; i++) { Map<String, Object> map = new HashMap<>(); map.put("img", imageResource[i]); list.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.cell, new String[]{"img"}, new int[]{R.id.image}); gridView.setAdapter(simpleAdapter); - ArrayAdapter
- SimpleCursorAdapter
- BaseAdapter
- Spinner 下拉列表
- setOnItemSelectedListener 选中监听器
- entries 数组资源
- ScrollView 滚动条
- 向下滚动条
- 横向滚动条HorizontalScrollView
- 选项卡
- TabHost
- TabWidget
- TabContent
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"></TabWidget> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </TabHost><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/left1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="Hello World" android:textSize="30sp" /> </LinearLayout>package com.example.tabhost; import android.os.Bundle; import android.view.LayoutInflater; import android.widget.TabHost; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TabHost tabHost = findViewById(android.R.id.tabhost); //初始化 tabHost.setup(); LayoutInflater layoutInflater = LayoutInflater.from(this); layoutInflater.inflate(R.layout.tab1, tabHost.getTabContentView()); layoutInflater.inflate(R.layout.tab2, tabHost.getTabContentView()); layoutInflater.inflate(R.layout.tab3, tabHost.getTabContentView()); tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("测试1").setContent(R.id.left1)); tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("测试2").setContent(R.id.right)); tabHost.addTab(tabHost.newTabSpec("tab3").setIndicator("测试3").setContent(R.id.left3)); } }
- 文本框组件textView
- activity
-
概述 代表手机屏幕的一屏
-
4种状态度
- 运行
- 暂停
- 停止
- 销毁
-
生命周期
- onCreate
- onStart
- onResume
- onPause
- onStop
- onDestory
- onRestart
-
创建并配置
- 创建类
- 继承Activity
- 重写onCreate方法
- setContent
-
启动与关闭
- startActivity(Intent)
- finish()
package com.example.activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.bt); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "测试", Toast.LENGTH_SHORT).show(); Log.i("测试", "测试"); Intent intent = new Intent(MainActivity.this, MyActivity.class); startActivity(intent); } }); Button button1 = findViewById(R.id.bt1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); }
} ```
-
多个Activity交换数据
-
储存值
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.save); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //获取数据 String name = ((EditText) (findViewById(R.id.name))).getText().toString(); String phone = ((EditText) (findViewById(R.id.phone))).getText().toString(); String adress = ((EditText) (findViewById(R.id.adress))).getText().toString(); String deatilAdress = ((EditText) findViewById(R.id.deatilAdress)).getText().toString(); //验证 if (!"".equals(name) && !"".equals(phone) && !"".equals(adress) && !"".equals(deatilAdress)) { //创建intent Intent intent = new Intent(MainActivity.this, Main2Activity.class); Bundle bundle = new Bundle(); //储存值 bundle.putCharSequence("name", name); bundle.putCharSequence("phone", phone); bundle.putCharSequence("adress", adress); bundle.putCharSequence("deatilAdress", deatilAdress); intent.putExtras(bundle); startActivity(intent); } else { Toast.makeText(MainActivity.this, "请将收货地址填写完整!!", Toast.LENGTH_SHORT).show(); } } }); } -
获取值
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Bundle bundle = getIntent().getExtras(); String name = bundle.getString("name"); String phone = bundle.getString("phone"); String adress = bundle.getString("adress"); String deatilAdress = bundle.getString("deatilAdress"); ((TextView) findViewById(R.id.name)).setText(name); ((TextView) findViewById(R.id.phone)).setText(phone); ((TextView) findViewById(R.id.adress)).setText(adress + deatilAdress); } }
-
-
切换Activity返回结果
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); //返回后的操作 if (requestCode == 0x1234 && resultCode == 0x1234) { //获取数据包 Bundle bundle = data.getExtras(); int imageId = bundle.getInt("imageId"); //设置头像 ImageView imageView = findViewById(R.id.image); imageView.setImageResource(imageId); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.choose); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, Main2Activity.class); startActivityForResult(intent, 0x1234); } }); }private int[] imageResource = new int[]{ R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1, R.drawable.img1 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); GridView gridView = findViewById(R.id.gridView); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); for (int i = 0; i < imageResource.length; i++) { Map<String, Object> map = new HashMap<>(); map.put("image", imageResource[i]); list.add(map); } SimpleAdapter simpleAdapter = new SimpleAdapter(this, list, R.layout.model, new String[]{"image"}, new int[]{R.id.img}); gridView.setAdapter(simpleAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = getIntent(); Bundle bundle = new Bundle(); bundle.putInt("imageId", imageResource[position]); intent.putExtras(bundle); setResult(0x1234, intent); finish(); } }); } -
Fragment
- 生命周期
- Fragment的创建
- 在Activity中添加Fragment
- 实例代码
<?xml version="1.0" encoding="utf-8"?> <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" tools:context=".MainActivity"> <LinearLayout android:id="@+id/test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"></LinearLayout> <!--按钮--> <GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:columnCount="6" android:paddingBottom="5dp"> <TextView android:layout_width="20dp" android:layout_height="wrap_content" android:layout_column="0" /> <ImageButton android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="1" android:layout_columnWeight="1" android:layout_marginStart="20dp" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/message" /> <ImageButton android:id="@+id/contact" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="2" android:layout_columnWeight="1" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/contact" /> <ImageButton android:id="@+id/discovery" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="3" android:layout_columnWeight="1" android:layout_gravity="center" android:background="#00FFFFFF" android:src="@drawable/discovery" /> <ImageButton android:id="@+id/my" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_column="4" android:layout_columnWeight="1" android:background="#00FFFFFF" android:scaleType="center" android:src="@drawable/my" /> <TextView android:layout_width="20dp" android:layout_height="wrap_content" android:layout_column="5" /> </GridLayout> </RelativeLayout>package com.example.test; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; /** 创建Fragment */ public class ContactFrament extends Fragment { @Nullable @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.contact, container, false); return view; } }package com.example.test; import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; /** * 使用与切换Fragment */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageButton messageButton = findViewById(R.id.message); View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); Fragment f = null; switch (v.getId()) { case R.id.message: f = new MessageFragment(); break; case R.id.contact: f = new ContactFrament(); break; case R.id.discovery: f = new DiscoveryFragment(); break; case R.id.my: f = new MyFragment(); break; default: break; } fragmentTransaction.replace(R.id.test, f); fragmentTransaction.commit(); } }; messageButton.setOnClickListener(onClickListener); ImageButton contactButton = findViewById(R.id.contact); contactButton.setOnClickListener(onClickListener); findViewById(R.id.discovery).setOnClickListener(onClickListener); findViewById(R.id.my).setOnClickListener(onClickListener); } }
-
Intent对象
-
属性
- Component name
- Action与Data
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.CALL_PHONE" />ImageButton telButton = findViewById(R.id.tel); ImageButton messageButton = findViewById(R.id.message); View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.tel: intent.setAction(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:1383838438")); startActivity(intent); break; case R.id.message: intent.setAction(Intent.ACTION_SENDTO); intent.setData(Uri.parse("smsto:10086")); intent.putExtra("sms_body", "测试"); startActivity(intent); default: break; } } }; telButton.setOnClickListener(onClickListener); messageButton.setOnClickListener(onClickListener); -
Extras属性 存放和获取数据
-
Flag属性 FLAG_ACTIVITY_NO_HISTORY
-
Intent种类
- 显示Intent
- 隐式Intent
-
-
- 事件和手势
- 单击事件
- 长按事件
//注册事件 findViewById(R.id.button) .setOnLongClickListener( new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { registerForContextMenu(v); openContextMenu(v); return true; } }); //创建菜单 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add("收藏"); menu.add("举报"); } - 物理按键事件
//按键事件 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //判断按键 if (keyCode == KeyEvent.KEYCODE_BACK) { exit(); return true; } return false; } //退出 private void exit() { if (System.currentTimeMillis() - exitTime >= 2000) { Toast.makeText(MainActivity.this, "再按一次返回键退出", Toast.LENGTH_SHORT).show(); exitTime = System.currentTimeMillis(); } else { finish(); System.exit(0); } } - 触摸事件
final Hat hat = new Hat(this); hat.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Toast.makeText(MainActivity.this, String.valueOf(hat.hatX), Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, String.valueOf(event.getX()), Toast.LENGTH_SHORT) .show(); hat.hatX = event.getX() - 310; hat.hatY = event.getY() - 200; hat.invalidate(); return true; } }); ((FrameLayout) findViewById(R.id.frameLayout)).addView(hat);package com.jamin.event; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.view.View; /** * @author Jamin <br> * @date 2019 /10/2 16:19 <br> * @desc 帽子 <br> */ public class Hat extends View { public float hatX; public float hatY; public Hat(Context context) { super(context); hatX = 100; hatY = 100; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.hat); canvas.drawBitmap(bitmap, hatX, hatY, paint); if (bitmap.isRecycled()) { bitmap.recycle(); } } } - 单击事件与触摸事件的区别
- 单击事件只触发一次
- 触摸事件触发两次
- 先触发单击事件的按下再抬起 如果返回true结束,返回false会再触发单击事件
- 手势检测 [查看相册的实例]
package com.jamin.event; import android.os.Bundle; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.ImageView; import android.widget.ViewFlipper; import androidx.appcompat.app.AppCompatActivity; public class Main2Activity extends AppCompatActivity implements GestureDetector.OnGestureListener { final int DISTANCE = 50; private int[] imageResource = new int[] { R.mipmap.img1, R.mipmap.img2, R.mipmap.img3, R.mipmap.img4, R.mipmap.img5, R.mipmap.img6 }; private GestureDetector detector; private ViewFlipper viewFlipper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); detector = new GestureDetector(Main2Activity.this, this); viewFlipper = findViewById(R.id.viewFlipper); for (int i = 0; i < imageResource.length; i++) { ImageView imageView = new ImageView(Main2Activity.this); imageView.setImageResource(imageResource[i]); viewFlipper.addView(imageView); } } @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) {} @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) {} @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // 向右边划 if (e1.getX() - e2.getX() > DISTANCE) { viewFlipper.showPrevious(); return true; } else if (e2.getX() - e1.getX() > DISTANCE) { viewFlipper.showNext(); return true; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { return detector.onTouchEvent(event); } }
- android应用的资源
-
字符串资源
-
颜色资源
-
尺寸资源dimans
-
drawable资源
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#f60" android:state_focused="true" /> <item android:color="#0a0" android:state_focused="false" /> </selector> -
mipmap资源
-
主题资源 Theme按钮,自定义style
-
菜单资源文件
- 选项菜单
- 重写onCreateOptionsMenu()方法 getMenuInflater().inflate();new Intent(),startActivity()}
- 重写onOptionsItemSelected()方法switch (item.getItemId()) {new Intent(),startActivity()}
- 上下文菜单
- 重写onCreateContextMenu() getMenuInflater().inflate(R.menu.menu, menu);
- 重写onContextItemSelected() switch(item.getItemId())
- 选项菜单
-
android 国际化
- values-en-rUS
- values-Zh-rCN
- values-zh-rTW
-
- ActionBar
未完成-
显示与关闭ActionBar
- 使用theme
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
- 使用theme
-
ActionBar Tab
-
层级式导航
//开启返回按钮 if (NavUtils.getParentActivityName(Main2Activity.this) != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
-
- 消息,通知
- 提示Toast
- 对话框AlertDialog
- 确定取消对话框
@Override public void onClick(View v) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setIcon(R.drawable.ic_launcher_background); alertDialog.setTitle("标题"); alertDialog.setMessage("内容"); alertDialog.setButton( DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您点击了取消按钮", Toast.LENGTH_SHORT).show(); } }); alertDialog.setButton( DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您点击了确定按钮", Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); } - 列表对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.ic_launcher_background); builder.setTitle("请选择"); builder.setItems( strings, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText( MainActivity.this, "您选择的是" + strings[which], Toast.LENGTH_SHORT) .show(); } }); builder.create().show(); } - 单选对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("测试"); builder.setSingleChoiceItems( strings, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText( MainActivity.this, "您选择的是" + strings[which], Toast.LENGTH_SHORT) .show(); } }); builder.setPositiveButton("确认", null); builder.create().show(); } - 多选对话框
@Override public void onClick(View v) { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("测试"); final boolean[] booleans = new boolean[] {true, false, false, true}; builder.setMultiChoiceItems( strings, booleans, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { Toast.makeText( MainActivity.this, "您选择的是" + booleans[which], Toast.LENGTH_SHORT) .show(); } }); builder.setPositiveButton("确认", null); builder.create().show(); }
- 确定取消对话框
- 通知Notification
// 通知管理器 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // 通知对象 Notification.Builder notification = new Notification.Builder(MainActivity.this); // 打开后自动关闭 notification.setAutoCancel(true); // 标题 notification.setContentTitle("通知标题"); // 内容 notification.setContentText("通知内容"); // 图标 notification.setSmallIcon(R.mipmap.ic_launcher); // 通知发送时间 notification.setWhen(System.currentTimeMillis()); // 设置声音和振动 notification.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE); // 创建一个启动的Intent Intent intent = new Intent(MainActivity.this, Main2Activity.class); PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0); notification.setContentIntent(pendingIntent); notificationManager.notify(NOTIFYID, notification.build()); - 广播
// 发送广播 Intent intent = new Intent(); intent.setAction("ceshi"); sendBroadcast(intent);package com.jamin.boardcastreceiver; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.view.WindowManager; import android.widget.Toast; /** * @author Jamin <br> * @date 2019/10/8 10:45 <br> * @desc 接收广播 <br> */ public class Receiver extends BroadcastReceiver { private static final String ACTION1 = "ceshi"; @Override public void onReceive(final Context context, Intent intent) { // 收到广播回复 if (intent.getAction().equals(ACTION1)) { AlertDialog alertDialog = new AlertDialog.Builder(context).create(); alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST); alertDialog.setIcon(R.mipmap.ic_launcher); alertDialog.setTitle("测试"); alertDialog.setMessage("测试内容"); alertDialog.setButton( DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "收到测试信息", Toast.LENGTH_SHORT).show(); } }); alertDialog.setButton( DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(context, "收到测试信息", Toast.LENGTH_SHORT).show(); } }); alertDialog.show(); } } } - 设置闹钟
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TimePicker timePicker = findViewById(R.id.timePicker); timePicker.setIs24HourView(true); findViewById(R.id.setting) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 创建intent对象 Intent intent = new Intent(MainActivity.this, AlarmActivity.class); // 获取显示闹钟的pendingIntent对象 PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, intent, 0); // 获取AlarmManager对象 AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); // 设置闹钟时间 Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, timePicker.getCurrentHour()); calendar.set(Calendar.MINUTE, timePicker.getCurrentMinute()); calendar.set(Calendar.SECOND, 0); // 设置一个闹钟 alarmManager.set( AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); Toast.makeText(MainActivity.this, "设置成功", Toast.LENGTH_SHORT).show(); } }); }
- 画图与动画
- 绘制矩形
Paint paint = new Paint(); paint.setColor(0xFFFF0000); paint.setAntiAlias(true); paint.setTextAlign(Paint.Align.LEFT); paint.setTextSize(30); canvas.drawText("测试", 105, 102, paint); - 绘制文字
Paint paint = new Paint(); String path = Environment.getExternalStorageDirectory() + "/1.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); canvas.drawBitmap(bitmap, 0, 0, paint); - 绘制图片
Paint paint = new Paint(); String path = Environment.getExternalStorageDirectory() + "/1.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); canvas.drawBitmap(bitmap, 0, 0, paint); - 绘制路径
Paint paint = new Paint(); paint.setColor(0xFF000000); paint.setAntiAlias(true); paint.setStrokeWidth(1); paint.setTextSize(30); paint.setStyle(Paint.Style.STROKE); Path path = new Path(); path.addCircle(100, 200, 60, Path.Direction.CW); // canvas.drawPath(path, paint);canvas.drawPath(path, paint); canvas.drawTextOnPath("中华人民共和国", path, 100, 200, paint); - 逐帧动画
<?xml version="1.0" encoding="utf-8"?> <!--逐帧动画资源文件--> <animation-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@mipmap/img1" android:duration="60" /> <item android:drawable="@mipmap/img2" android:duration="60" /> <item android:drawable="@mipmap/img3" android:duration="60" /> <item android:drawable="@mipmap/img4" android:duration="60" /> </animation-list><!--使用动画资源--> android:background="@drawable/anim" - 补间动画
- 透明度渐变动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 持续时间 完全透明到完全不透明--> <alpha android:duration="2000" android:fromAlpha="0" android:toAlpha="1" /> </set>// 使用动画资源 Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.anim4); imageView.startAnimation(animation);
- 透明度渐变动画
- 旋转动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--开始角度 最终角度 xy轴 持续时间--> <rotate android:duration="2000" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="360" /> </set> - 缩放动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--持续时间 从xy的0.5到1 中心点--> <scale android:duration="2000" android:fromXScale="0.5" android:fromYScale="0.5" android:pivotX="50%" android:pivotY="50%" android:toXScale="1" android:toYScale="1" /> </set> - 平移动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <!--起始点到终点 持续时间--> <translate android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="300" android:toYDelta="0" /> </set>
- 绘制矩形
- 音频视频
- 音频
package com.example.musicvideo; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; /** * @author Jamin * @date 2019/10/9 * @desc 使用mediaPlayer简易播放器 */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final MediaPlayer mediaPlayer = MediaPlayer.create(MainActivity.this, R.raw.mp31); findViewById(R.id.start) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 音频播放 mediaPlayer.start(); } }); findViewById(R.id.pause) .setOnClickListener( new View.OnClickListener() { // 音频暂停 @Override public void onClick(View v) { mediaPlayer.pause(); } }); findViewById(R.id.stop) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // 音频停止 mediaPlayer.pause(); mediaPlayer.seekTo(0); } }); String path = Environment.getExternalStorageDirectory() + "/mp31.mp3"; Log.i("测试", path); final MediaPlayer mediaPlayer1 = MediaPlayer.create(MainActivity.this, Uri.parse(path)); final ImageButton playPause = findViewById(R.id.play); playPause.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mediaPlayer1.isPlaying()) { mediaPlayer1.pause(); ((ImageButton) v).setImageDrawable(getResources().getDrawable(R.mipmap.start)); } else { mediaPlayer1.start(); ((ImageButton) v).setImageDrawable(getResources().getDrawable(R.mipmap.pause)); } } }); ImageButton stop = findViewById(R.id.stop2); stop.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer1.pause(); mediaPlayer1.seekTo(0); playPause.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } }); } }ListView listView = findViewById(R.id.listView); // 音频属性,使用场景 音效类型 AudioAttributes audioAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .build(); // 创建soundPool对象 配置相关参数 final SoundPool soundPool = new SoundPool.Builder().setAudioAttributes(audioAttributes).setMaxStreams(10).build(); // 将音频资源放入hashMap中 final HashMap<Integer, Integer> hashMap = new HashMap<>(); // 加载音频,优先权 值越大优先权越高 hashMap.put(0, soundPool.load(MainActivity.this, R.raw.nomatter, 1)); hashMap.put(1, soundPool.load(MainActivity.this, R.raw.nextofkin, 1)); hashMap.put(2, soundPool.load(MainActivity.this, R.raw.makingmefeel, 1)); listView.setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 资源文件,左声道音量0-1,右声道音量,优先级值越大优先级越高,循环,速率0.5-2 soundPool.play(hashMap.get(position), 1, 1, 0, 0, 1); } });
- MediaPlayer与SoundPool区别
- MediaPlayer 延迟长,占用资源多,不支持同时播放多个音频
- SoundPool延迟短,占用资源少,支持多音频播放
-
视频
package com.example.musicvideo; import android.media.MediaPlayer; import android .os.Bundle; import android.os.Environment; import android.util.Log; import android.widget.MediaController; import android.widget.Toast; import android.widget.VideoView; import androidx.appcompat.app.AppCompatActivity; import java.io.File; public class Main2Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); VideoView videoView = findViewById(R.id.videoView); // 控制组件 videoView.setMediaController(new MediaController(Main2Activity.this)); String path = Environment.getExternalStorageDirectory() + "/mp41.mp4"; Log.i("测试", path); File file = new File(path); if (file.exists()) { videoView.setVideoPath(file.getAbsolutePath()); Toast.makeText(Main2Activity.this, "文件存在", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Main2Activity.this, "文件不存在", Toast.LENGTH_SHORT).show(); } // 获取焦点 videoView.requestFocus(); videoView.start(); // 播放完毕触发事件 videoView.setOnCompletionListener( new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Toast.makeText(Main2Activity.this, "播放完毕", Toast.LENGTH_SHORT).show(); } }); } }package com.example.musicvideo; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Environment; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.ImageButton; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; /** * @author Jamin * @date 2019/10/10 * @desc 使用mediaPlayer+surfaceView实现播放视频 */ public class Main3Activity extends AppCompatActivity { private boolean isPause = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); SurfaceView surfaceView = findViewById(R.id.surfaceView); final SurfaceHolder surfaceHolder = surfaceView.getHolder(); final MediaPlayer mediaPlayer = new MediaPlayer(); // 设置多媒体类型 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); try { mediaPlayer.setDataSource(Environment.getExternalStorageDirectory() + "/mp41.mp4"); // 预加载 mediaPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } final ImageButton playButton = findViewById(R.id.start3); playButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } else { // 将视频输出到surfaceView mediaPlayer.setDisplay(surfaceHolder); mediaPlayer.start(); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.pause)); } } }); findViewById(R.id.stop3) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaPlayer.pause(); mediaPlayer.seekTo(0); playButton.setImageDrawable(getResources().getDrawable(R.mipmap.start)); } }); } } -
控制相机
package com.example.musicvideo; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PixelFormat; import android.hardware.Camera; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.widget.ImageButton; import android.widget.Toast; import androidx.core.content.ContextCompat; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * @author Jamin * @date 2019/10/10 * @desc 拍照与录像 */ public class Main4Activity extends Activity implements SurfaceHolder.Callback { private Camera camera; private SurfaceView surfaceView; private SurfaceHolder surfaceViewHolder; private int cameraId = 0; private ImageButton takePhoto; private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 根据拍照数据创建位图 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); // 停止预览 camera.stopPreview(); File dir = new File(Environment.getExternalStorageDirectory() + "/DCIM/Camera/"); if (!dir.exists()) { // 创建文件夹 dir.mkdir(); } String fileName = System.currentTimeMillis() + ".jpeg"; File file = new File(dir, fileName); try { FileOutputStream fileOutputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 将图片添加到系统图库 try { MediaStore.Images.Media.insertImage( Main4Activity.this.getContentResolver(), file.getAbsolutePath(), fileName, null); } catch (FileNotFoundException e) { e.printStackTrace(); } // 通知图库更新 Main4Activity.this.sendBroadcast( new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + ""))); // 保存图片 Toast.makeText(Main4Activity.this, "照片保存至" + file, Toast.LENGTH_SHORT).show(); camera.startPreview(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main4); this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); initView(); initButton(); } private void initButton() { takePhoto = findViewById(R.id.imgbt1); takePhoto.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { camera.takePicture(null, null, pictureCallback); } }); } private void initView() { surfaceView = findViewById(R.id.surface); surfaceViewHolder = surfaceView.getHolder(); surfaceViewHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { if (ContextCompat.checkSelfPermission(Main4Activity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(Main4Activity.this, "请先打开权限", Toast.LENGTH_LONG).show(); } else { cameraOpen(); } } private void cameraOpen() { try { // 打开相机 camera = Camera.open(cameraId); // 反转 camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceViewHolder); camera.startPreview(); // 自动对焦 camera.autoFocus(null); } catch (IOException e) { e.printStackTrace(); camera.release(); camera = null; Toast.makeText(Main4Activity.this, "不能打开摄像机", Toast.LENGTH_SHORT).show(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 设置参数 Camera.Parameters parameters = camera.getParameters(); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality", 80); camera.setParameters(parameters); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.stopPreview(); camera.release(); camera = null; } @Override protected void onPause() { super.onPause(); // 释放资源 if (camera != null) { camera.stopPreview(); camera.release(); } } }package com.example.musicvideo; import android.Manifest; import android.content.pm.PackageManager; import android.hardware.Camera; import android.media.MediaRecorder; import android.os.Bundle; import android.os.Environment; import android.os.SystemClock; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Chronometer; import android.widget.ImageButton; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; /** * @author Jamin * @date 2019/10/11 * @desc 视频录制 */ public class Main5Activity extends AppCompatActivity implements SurfaceHolder.Callback { private File videoFile; private MediaRecorder mediaRecorder; private Camera camera; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private int cameraId = 0; private Camera.Parameters parameters; private Chronometer chronometer; private ImageButton stopVideo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main5); surfaceView = findViewById(R.id.surface2); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(this); chronometer = findViewById(R.id.chronometer); final ImageButton videoButton = findViewById(R.id.imgbt2); videoButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { record(); // 开始录像后开始按钮不可点击 videoButton.setEnabled(false); // 停止按钮可点击 stopVideo.setEnabled(true); } }); stopVideo = findViewById(R.id.imgbt3); // 设置停止按钮不可点击 stopVideo.setEnabled(false); stopVideo.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mediaRecorder.stop(); chronometer.stop(); chronometer.setBase(SystemClock.elapsedRealtime()); Toast.makeText( Main5Activity.this, "视频保存至" + videoFile.getAbsolutePath(), Toast.LENGTH_SHORT) .show(); // 录像结束后开始按钮可点击 videoButton.setEnabled(true); stopVideo.setEnabled(false); } }); } @Override protected void onResume() { super.onResume(); camera = Camera.open(); } @Override protected void onPause() { super.onPause(); camera.stopPreview(); camera.release(); } /** 开始录制 */ private void record() { settingMediaRecorder(); // 准备录像 try { mediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } // 开始录像 mediaRecorder.start(); chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); } /** 录像配置 */ public void settingMediaRecorder() { File path = new File(Environment.getExternalStorageDirectory() + "/MyVideo"); if (!path.exists()) { path.mkdir(); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM-dd HH:mm:ss"); String fileName = simpleDateFormat.format(new Date()) + ".mp4"; videoFile = new File(path, fileName); mediaRecorder = new MediaRecorder(); // camera.setDisplayOrientation(90); // 解锁相机 camera.unlock(); // 使用相机 mediaRecorder.setCamera(camera); mediaRecorder.reset(); // 使用麦克风和相机获取视频音频 mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 输出格式 mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 编码格式 mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置比特率 mediaRecorder.setVideoEncodingBitRate(1080 * 1920); // 设置分辨率 List<Camera.Size> supportedVideoSizes = parameters.getSupportedVideoSizes(); for (Camera.Size size : supportedVideoSizes) { if (size.width / 16 == size.height / 9) { mediaRecorder.setVideoSize(size.width, size.height); Log.d("setPictureSize", "SET width:" + size.width + " height " + size.height); break; } } // 设置帧率 mediaRecorder.setVideoFrameRate(24); // 输出路径 mediaRecorder.setOutputFile(videoFile.getAbsolutePath()); // 预览 mediaRecorder.setPreviewDisplay(surfaceHolder.getSurface()); // 调整角度 mediaRecorder.setOrientationHint(90); } /** * 权限检测 * * @param holder */ @Override public void surfaceCreated(SurfaceHolder holder) { if (ContextCompat.checkSelfPermission(Main5Activity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(Main5Activity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(Main5Activity.this, "请先打开权限", Toast.LENGTH_LONG).show(); } else { cameraOpen(); } } /** 打开相机 */ private void cameraOpen() { try { // 打开相机 camera = Camera.open(cameraId); // 反转 camera.setDisplayOrientation(90); camera.setPreviewDisplay(surfaceHolder); camera.startPreview(); } catch (IOException e) { e.printStackTrace(); camera.release(); camera = null; Toast.makeText(Main5Activity.this, "不能打开摄像机", Toast.LENGTH_SHORT).show(); } } /** * 设置相机参数 * * @param holder * @param format * @param width * @param height */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { parameters = camera.getParameters(); parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); camera.setParameters(parameters); camera.startPreview(); } /** * 销毁操作 * * @param holder */ @Override public void surfaceDestroyed(SurfaceHolder holder) { if (camera != null) { camera.release(); camera = null; } } }
- 音频