最近一直在忙学校的新生杯扫地机器人irobot项目app,现在对开发过程中的一些问题进行总结。
一、因为App中需要用到较多按钮,固然可以一个一个地设置setOnClickListener,但也可以进行优化,代码如下
Button btn1,btn2; btn1 = (Button)findViewById(R.id.btn1); btn2 = (Button)findViewById(R.id.btn2); View.OnclickListener listener = new OnclickListener(){ @Override public void onClick( View view){ switch(view.getId()){ case R.id.btn1: Log.d("btn1"," has been clicked! "); break; case R.id.btn2: Log.d("btn2","has been clicked !"); break; default: break; } } } btn1.setOnclickListener(listener); btn2.setOnclickListener(listener);
二、做的时候我在考虑怎么优化按钮的外观,发现用alpha可以改变按钮的透明度,代码如下:
android:alpha="1.0" <!-- 在XML中取值为0到1,0为完全透明,1为完全不透明,
除此之外,可以在用imageView.setAlpha(xxx);来实现(这里xxx的取值范围为0-255) -->
如何做出别的形状的按钮:
① 可以在Drawable 文件下下创建一个shape 的XML,示例代码如下:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffff00"/> <stroke android:width="2dp" android:color="#ff00ff"/> <corners android:bottomLeftRadius="20dp" android:bottomRightRadius="20dp" android:topLeftRadius="20dp" android:topRightRadius="20dp"/> <gradient android:startColor="#ff0000" android:endColor="#ffffff" android:type="radial" android:centerX="0.5" android:centerY="0.5" android:gradientRadius="500dp" /> <padding android:bottom="15dp" android:top="15dp" android:left="15dp" android:right="15dp" /> </shape>
corners用来设置圆角按钮
gradient设置渐变颜色,有liner,radial等选项,endColor和startColor为渐变的起始和终止渐变颜色
padding为设置文字与四边的间距
stroke为设置边框属性
完成该XML的创建后可以在要创建的Button中用background来设置:
android:background="@drawable/button_test"
② 也可以用ImageButton来设置,直接用src来设置想要作为背景的图片
(PS:这边我还遇到了一个小问题,即drawable下放入的图片只能用小写字母,且不能以数字开头)
三、关于如何设置标题栏
我发现app的标题栏在我的app中显得out of place, 于是实现标题栏的隐藏
① 在AndroidManifest中的<activity>下设置:
android:theme="@android:style/Theme.Holo.NoActionBar"
②在Java Class 中调用actionbar的hide方法
(第一行代码上的方法就是这个,进一步可以用back键绑定((Activity) getContext().finish();)来实现返回效果 )
如果想实现自定义的标题栏,新建XML(绑定事件的话再新建java class) 然后在布局中inflate
四、引入自定义字体的方法:
1、在网上下载字体文件(.ttf),并在工程目录的./main下,新建assets/fonts文件夹,并把.ttf文件放入其
中,如图
当然,如果不想在网上下载的话,就在C:\Windows\fonts下寻找对应的.ttf文件
2、在想要应用自定义字体的Activity Class中引入对应字体,代码如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView textView; textView = (TextView) findViewById(R.id.textview1); Typeface typeface = Typeface.createFromAsset(getAssets(),"fonts/LHANDW.TTF"); textView.setTypeface(typeface); if (savedInstanceState == null) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); BluetoothChatFragment fragment = new BluetoothChatFragment(); transaction.replace(R.id.sample_content_fragment, fragment); transaction.commit(); } }
这里只在TextView 中加载了对应字体
五、调整ProgressBar的外观:
final ProgressDialog progressDialog = new ProgressDialog(Welcome.this); progressDialog.setMessage("Loading..."); progressDialog.setCancelable(false); progressDialog.show(); Point size = new Point(); progressDialog.getWindow().getWindowManager().getDefaultDisplay().getSize(size); //一定要用progressDialog去得到 int width = size.x; int height = size.y; WindowManager.LayoutParams params = progressDialog.getWindow().getAttributes(); params.alpha = 1.0f; //设置进度条透明度 params.height = height/8; //设置进度条高度 params.gravity = Gravity.CENTER; params.width = 4*width/5; params.dimAmount = 0f; //设置半透明背景的灰度
六、关于用iRobot播放音乐
关键问题是得到音乐文件的二进制编码,由于下载的MP3或者MP4文件就是二进制的,这里直接用UltraEdit
打开就行。当然,考虑到MP4文件过大,而这里我们不需要那么好的播放效果,可以用.midi格式替代,大小只有
十几或者几十KB,却能包含数十条音
轨,这里截了一个关于百度百科对midi格式的说明,如下图:
七、蓝牙的连接
这个项目的核心问题就是要实现手机端与irobot上蓝牙模块的连接,这里我是下载的Github上的源码。结果发现连接不上。
一开始我以为是PIN码问题,后来发现不是,PIN码是用来实现配对的,这个配对可以在Android 手机中的Settings内完成,默认
的PIN码是1234或0000。而我是连接失败,这个连接问题一般是UUID问题。
UUID是设备的唯一识别码,由三部分组成,当前的日期和时间、时钟序列、全球唯一的IEEE设备识别号,如果有网卡,从
网卡MAC地址获得。UUID一般会比较长,对此使用比较广泛的是微软的GUID,在JAVA中可以用以下代码生成
import java.util.UUID; public class Test { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); System.out.println (uuid); } }
扯远了,我后来把源代码中的UUID修改了一下,发现竟然连接上了!具体原理大概是蓝牙串口通信或是不同的通信服务
需要特定的UUID吧,这里附上一个链接参考:https://blog.csdn.net/spmno/article/details/6931941
private static final UUID MY_UUID_SECURE = //UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private static final UUID MY_UUID_INSECURE = //UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
八、生成正式的.apk
注意如果res目录下的文件不是.png格式的就会出错,如果都是.png还是无法生成的话,可以试试删除图片重新下载或者
invalidate cache
九、Rockerview的引入
为了增强操作性,我通过引入第三方库另增了一个虚拟摇杆界面,可以在手指触摸的时候显示机器人前进的方向和速度值。
如图所示
十、横屏显示
因为这里我用了虚拟摇杆和几个按键组成的界面,横屏显示会更美观。步骤如下:
在res目录下新建resource file ,导入orientation, 并选择Landscape(landscape为横屏,portrait为纵向显示)
然后修改对应的Activity中的setcontentview即可,如图
十一、引入重力传感器
也是为了让我这个巨丑的界面显得更加酷炫,我加了个重力传感器,代码如下:
sensorManager =(SensorManager) getSystemService(Context.SENSOR_SERVICE); Sensor accelerometersensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); Sensor magneticsensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); sensorManager.registerListener(listener,accelerometersensor,SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(listener,magneticsensor,SensorManager.SENSOR_DELAY_GAME);
@Override protected void onDestroy() { super.onDestroy(); if(sensorManager!=null){ sensorManager.unregisterListener(listener); } } private SensorEventListener listener = new SensorEventListener() { float[] accelerometerValues = new float[3]; float[] magneticValues = new float[3]; @Override public void onSensorChanged(SensorEvent event) { // 判断当前是加速度传感器还是地磁传感器 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 注意赋值时要调用clone()方法 accelerometerValues = event.values.clone(); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { // 注意赋值时要调用clone()方法 magneticValues = event.values.clone(); } float[] R = new float[9]; float[] values = new float[3]; SensorManager.getRotationMatrix(R, null, accelerometerValues, magneticValues); SensorManager.getOrientation(R, values); Log.d("MainActivity", "value[0] is " + Math.toDegrees(values[0])); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } };
这里采用的是加速度传感器和磁力传感器,代码我也是看的郭神的《第一行代码》上的。然后在Androidmanifest文件中加入以下支持:
<uses-permission android:name="android.permission.BODY_SENSORS"/>
表示加入传感器的权限,接着再在安卓手机的设置界面里找到权限,给对应app开启身体传感器权限。这里要注意如果不先在Androidmanifest 中加入对应支持,是无法在app中找到对应权限的。
项目代码:https://github.com/550517968/iRobot