通话记录项目总结

      之前做的通话记录部分做一个总结,通话记录在整个联系人应用中占一个fragment,主要是显示了近段时间的所有通话和未接来电,这部分不是我写的不做重点介绍,主要说一下点击进入已保存联系人和未保存联系人的详细通话界面,还有未接来电的个数图标显示。

      通话记录显示界面是CalllogGroupFragment,它继承了ListFragment更好的显示,实现了2个接口:implements CallLogQueryHandler.Listener, 进入这个接口看到:

/** Listener to completion of various queries. */
    public interface Listener {

        /**
         * Called when {@link CallLogQueryHandler#fetchCalls(int)}complete.
         */
        void onCallsFetched(Cursor combinedCursor);
    }

    字面义很明显的是说,查询完成就 调用这个方法,具体做什么我们自己在fragment实现:

	@Override
	public void onCallsFetched(Cursor cursor) {
		if (getActivity() == null || getActivity().isFinishing()) {
			return;
		}
		mAdapter.setLoading(false);
		
		/*****************/
		
		mAdapter.changeCursor(cursor);
		// This will update the state of the "Clear call log" menu item.
		getActivity().invalidateOptionsMenu();
		if (mScrollToTop) {
			final ListView listView = getListView();
			// The smooth-scroll animation happens over a fixed time per
iod.
			// As a result, if it scrolls through a large portion of 
the list,
			// each frame will jump so far from the previous one that 
the user
			// will not experience the illusion of downward motion. 
Instead,
			// if we're not already near the top of the list, we 
instantly jump
			// near the top, and animate from there.
			if (listView.getFirstVisiblePosition() > 5) {
				listView.setSelection(5);
			}
			// Workaround for framework issue: the smooth-scroll doesn't
			// occur if setSelection() is called immediately before.
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					if (getActivity() == null || getActivity()
.isFinishing()) {
						return;
					}
					listView.smoothScrollToPosition(0);
				}
			});

			mScrollToTop = false;
		}
		mCallLogFetched = true;
		destroyEmptyLoaderIfAl
	}

       就是更新listview显示数据 ,这个加载过程用的是AsyncQueryHandler,感觉这个代码有点复杂,而且android3.0之后有Loader可以更好的异步加载数据库,所以这里不对加载过程详细研究。loader写出来的更简洁推荐loader!然后是listview的点击事件其实封装到CallLogGroupAdapter这个adapter里面,而这个通话记录又是分为保存的联系人,为保存的联系人,单个或者几条在一起的群组,提取他的号码还是相当麻烦。包括通话记录的时间排序同一号码合并都放在CallLogGroupAdapter里面实现。

      接下来说一下未接来电个数的图标显示,类似于最新版QQ消息个数图标。我用的github的一个自定义控件叫BadgeView用法很简单:

mBadge=new BadgeView(this, mTabhost.getTabWidget(),1);
		if(mBadge!=null){
			updateBadge();
		}

private void updateBadge(){
        int count = getMissCallCount();
        mBadge.setText(count+"");
        if(count>0 ){
            mBadge.show();
        }else{
            mBadge.hide();
        }
	}

     是哪个面 两段代码就是new 控件,第二个参数就是 背景view的实例  第三个参数就是在第几个tab上显示,此处是第2个名称“最近通话”,然后最开始的时候的就用这样的代码写最近通话的tab标签:

mTabhost.addTab(createTab(mTabhost,TAB_TAG_CALLLOG,R.string.lb_calllog,R.drawable.
tabwidget_icon_calllog), CalllogGroupFragment.class, null);

  看上去没什么问题,最后运行报错  大致是说对象转型出错,然后看了BadgeView的源码: 我估计是必须要传一个ViewGroup进去,从另一个角度想, 怎么会让一个view覆盖在一个view上面呢???

private void applyTo(View target) {
		
		LayoutParams lp = target.getLayoutParams();
		ViewParent parent = target.getParent();
		FrameLayout container = new FrameLayout(context);
		
		if (target instanceof TabWidget) {
			
			// set target to the relevant tab child container
			target = ((TabWidget) target).getChildTabViewAt
(targetTabIndex);
			this.target = target;
			
			((ViewGroup) target).addView(container, 
					new LayoutParams(LayoutParams.FILL_PARENT, 
LayoutParams.FILL_PARENT));
			
			this.setVisibility(View.GONE);
			container.addView(this);
			
		} else {
			// TODO verify that parent is indeed a ViewGroup
			ViewGroup group = (ViewGroup) parent; 
			int index = group.indexOfChild(target);
			
			group.removeView(target);
			group.addView(container, index, lp);
			
			container.addView(target);
	
			this.setVisibility(View.GONE);
			container.addView(this);
			
			group.invalidate();
			
		}
		
	}

   后来老大帮我 改了一段 代码,把之前的添加标签页改成:

//====start=====
        FrameLayout fly=new FrameLayout(this);
        TextView indicator = new TextView(this);
        indicator.setText(getResources().getString(R.string.lb_calllog));
        indicator.setGravity(Gravity.CENTER);
        indicator.setBackgroundResource(R.drawable.tabwidget_background_color);
        indicator.setCompoundDrawablesWithIntrinsicBounds(0, 
R.drawable.tabwidget_icon_calllog, 0, 0);
        setPadding(indicator);
        fly.addView(indicator);
        
        TabSpec calllogTab = mTabhost.newTabSpec(TAB_TAG_CALLLOG).setIndicator(fly);
    
        //====end=====

    这个在外层加了一个 FrameLayout就OK了,这是因为createTab方法是这样的:可以看到就是一个TextView:

private TabSpec createTab(FragmentTabHost tabhost,String tag,int titleRes,
int iconRes){
        TextView indicator = new TextView(this);
        indicator.setText(titleRes);
        indicator.setGravity(Gravity.CENTER);
        indicator.setBackgroundResource(R.drawable.tabwidget_background_color);
        indicator.setCompoundDrawablesWithIntrinsicBounds(0, iconRes, 0, 0);
        setPadding(indicator);
        return tabhost.newTabSpec(tag).setIndicator(indicator);
    }

        那么这个问题就解决了,后来这个未接来电 有些bug:比如在另外的界面不能及时更新未接来电个数,那么这个就应该把更新个数分别写在主activity和当前fragment。 还有在当前界面有未接来电不能及时更新,在onResume()更新一下就好了

       最后部分就是联系人详情了,它分为已保存的联系人和陌生号码的详情,核心类就是一个AsyncTask读取数据库的通话记录,复杂的地方其实是对数据的封装 对记录的排序 时间格式的定制比如“今天” “昨天” “星期几”等等

        总之从这个项目,看到了google工程师代码的严谨与优化,包括异步操作数据库,每一条数据的封装,adapter里面点击条目号码的获取等等,自己在方面还有所欠缺。

   





    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值