Android:Moring-早安闹钟开发过程记录(四)

FragmentMenu侧滑菜单界面实现

1.界面实现

侧滑菜单.jpg
  • 界面显示比较简单,因为用的SlidingMenu的第三方库所以实现起来比较简单
    github地址:https://github.com/jfeinstein10/SlidingMenu
    -在新建一个侧滑菜单的布局文件,布局写成什么样菜单就长什么样
    显示菜单的Activity需要继承SlidingFragmentActivity
setBehindContentView(R.layout.menu_home);
//获取到slidingMenu对象SlidingMenu slidingMenu = getSlidingMenu();
slidingMenu.setMode(SlidingMenu.RIGHT);//设置菜单在哪一边
slidingMenu.setShadowWidthRes(R.dimen.shadow_width);
//设置阴影图片
slidingMenu.setShadowDrawable(R.drawable.shadow);
//设置为全屏拉出菜单
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
//设置菜单宽度
slidingMenu.setBehindOffset(200);

侧滑菜单就可以愉快的开始工作了

2.功能实现

天气和震动比较简单,用SP记录一下用户的选择就OK了
比较复杂的是更换城市和音量改变

  • 更换城市


    changecity.jpg
    • 在用户输入的时候给用户动态提示
      • 配置数据库
        首先配置好数据库,在第一次启动应用的时候将数据库拷贝到本地
in=getResources().getAssets().open(dbName);
out=new FileOutputStream(file);
byte[] buffer=new byte[1024];
int len=0;
while((len=in.read(buffer))!=-1){
          out.write(buffer, 0, len);
}
  定义一个工具类进行查找数据库,这里需要进行模糊查找
  `"select 字段名 from 表名 where 字段名like '%" + 用户输入的字符+ "%'"`
  将包含该字符的数据全部找出,返回String列表
public ArrayList<String> find(String input){
          String path="data/data/com.joe.lazyalarm/files/china_Province_city_zone.db";
          SQLiteDatabase sql=SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
          //模糊查询
          ArrayList<String> cityList=new ArrayList<String>();
          Cursor cursor=sql.rawQuery("select CityName from T_City where CityName like '%" + input + "%'", null);
          while (cursor.moveToNext()){
              String cityName=cursor.getString(cursor.getColumnIndex("CityName"));
              cityList.add(cityName);
          }
          sql.close();
          cursor.close();
          return cityList;
}
- 界面实现
  Android自己有一个控件叫AutoCompleteTextView-自动补全文本编辑框,用这个控件可以实现这个效果,与数据库建立连接就可以了。
  我没有用AutoCompleteTextView,而是自己实现这个效果。分析一下这个控件的效果不难得出就是一个EditText和一个ListView就可以实现
  - 布局文件:
<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android"    
android:layout_width="match_parent"    
android:layout_height="match_parent"    >
          <EditText
              android:id="@id/et_change_city"
              android:hint="例如:重庆"
              android:layout_width="match_parent"
              android:layout_height="wrap_content" />
          <ListView
              android:visibility="gone"
              android:layout_below="@id/et_change_city"
              android:id="@id/lv_change_city"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"/>
</RelativeLayout>

说明:我是通过setView()将布局添加到对话框中,为了省事并没有让ListView悬浮在对话框上面,如果需要悬浮的话改一下布局文件就可以了
因为ListView没有悬浮,必然会占用dialog的宽高,所以在初始化的时候将ListView的状态设置为gone,不设置也没有关系,因为代码中会设置输入一个字符后才开启提示
- 代码实现
首先将布局塞给对话框

dao = new CityDao();//数据库读取工具
cityList = new ArrayList<String>();//查找到的城市列表
final View autoLayout = View.inflate(mActivity, R.layout.auto_edit_view, null);
final EditText autoText = (EditText) autoLayout.findViewById(R.id.et_change_city);
ListView listHint = (ListView) autoLayout.findViewById(R.id.lv_change_city);
builder.setView(autoLayout);

然后为ListView设置一个Adapter
Adapter的getView()方法

@Override
public View getView(int position, View convertView, ViewGroup parent) {
          ViewHolder holder;
          if(convertView==null){
              convertView=View.inflate(mActivity,R.layout.item_change_city,null);
              holder=new ViewHolder();
              holder.hint= (TextView) convertView.findViewById(R.id.tv_hint_city);
              convertView.setTag(holder);
          }else{
              holder= (ViewHolder) convertView.getTag();
          }
          holder.hint.setText(cityList.get(position));
          return convertView;
      }

适配器设置好了以后,就需要监听文本框的输入情况来动态改变ListView
EditText有一个方法addTextChangedListener(TextWather tw);用于监听文本框的文字改变,在onTextChanged中实现显示提示

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
          if (s.length() > 0) {
              Log.d("changecity", "显示listview");
              //如果字符大于0,显示listview
              listHint.setVisibility(View.VISIBLE);
              cityList = dao.find(s.toString());
              adapter.notifyDataSetChanged();
          } else {
              listHint.setVisibility(View.GONE);
          }
}

每当文字发生改变时获取到用户输入的字符,查找数据库更新cityList并刷新UI。
还有一个问题,由于每次查询返回的数据条数不一致,导致有时候数据条数太多ListView太长被键盘盖住了。这里还需要限制一下ListView的高度
int itemCount=adapter.getCount()
获取到当前的数据条数,如果条数大于四条就将ListView限制死,如果小于四条就以ListView本身的高度为准,在onTextChanged中添加

int itemCount = adapter.getCount();
Log.d("changecity", "count" + itemCount);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) listHint.getLayoutParams();
if (itemCount > 4) {
          params.height = 500;
} else {
          params.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
}
listHint.setLayoutParams(params);

最后一步,监听ListView的Item点击事件,实现用户点击提示补全编辑框
点击后提示消失

listHint.setOnItemClickListener(new AdapterView.OnItemClickListener() {
          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
              TextView cityName= (TextView) view.findViewById(R.id.tv_hint_city);
              autoText.setText(cityName.getText());
              listHint.setVisibility(View.GONE);
          }
      });

大功告成!

  • 音量控制
    利用SeekBar来改变音量,首先在用户滑动了SeekBar的时候要播放铃声(不然调屁的音量啊!)
    设置SeekBar的监听,在onProgressChanged()中去实现逻辑
    setOnSeekBarChangeListener(OnSeekBarChangeListener listener);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
          playAlarmMusic();//播放音乐
          setSystemVolume(progress);//调节音量
          PrefUtils.putInt(mActivity, ConsUtils.ALARM_VOLUME, progress);//记录音量
}

现在依次来写出这两个方法吧,首先是播放音乐

//播放音乐
      private void playAlarmMusic() {
          if(mPlayer==null){
              try {
                  mPlayer=new MediaPlayer();
                  AssetFileDescriptor assetFileDescriptor=mActivity.getAssets().openFd("everybody.mp3");
                  mPlayer.reset();
                  mPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
                  mPlayer.setDataSource(assetFileDescriptor.getFileDescriptor(), assetFileDescriptor.getStartOffset(), assetFileDescriptor.getLength());
                  mPlayer.setVolume(1f, 1f);
                  mPlayer.prepare();
                  mPlayer.start();
                  isMusicOn=true;
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }

必须将mPlayer的AudioStreamType设置为某一个类型,否则是没有什么卵用的,因为是闹钟所以就设置为STREAM_ALARM就好
另外因为每次滑动都会调用该方法,所以先判断一下当前是否已经在播放了,在播放了就不有再播放了。
isMusicOn是做一个标记为后面关掉音乐用

- AudioManager来设置音量

AudioManager是系统服务通过getSystem(AUDIO_SERVICE)得到实例

private void setSystemVolume(int progress) {
          //获取到音量调节管理器
          int maxVolume= mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
          int setVolume=(maxVolume*progress)/100;
          mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, setVolume, 0);
}

setStreamVolume()中的第二个参数的解释是传入音量的绝对值,我的理解是音量绝对值可能不一定是百分数,所以先获取到手机的最大音量值,然后通过百分比计算应该传入的绝对值(一定要先乘再除啊,否则int类型你懂得,误差会比较大),具体绝对值是什么我也没去研究,不过这样做应该没有太大的问题。
获取和修改系统音量需要用到的权限

<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
写到这儿,这个项目基本上比较重要的地方都总结完了,另外为了防止应用被无情的杀死,我翻看了很多大神的博客,目前比较有效的应该是开启一个独立进程相互监视,互相扶持~,后面有空的话再补一篇吧!

完结!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容