手机影音项目笔记(一)
来源:互联网 发布:au下载 免费中文版mac 编辑:程序博客网 时间:2024/04/28 05:48
01、 抽取BaseActivity
抽取BaseActivity的好处:
l 处理共同操作(避免代码重复,提高代码可维护性)
l 代码规范(方便阅读代码,方便理解代码,阅读代码的时间占85%)
l 可以提供常用变量、方法(方便调用,避免代码重复)
public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(getLayoutId()); initView(); initListener(); initData(); registerCommonBtn();//注册返回按钮监听 } // 在多个界面都有的点击按钮,可以在这个方法注册监听 private void registerCommonBtn() { View view = findViewById(R.id.back); if (view != null){ view.setOnClickListener(this); } } /** 返回当前 Activity 使用的布局id*/ protected abstract int getLayoutId(); /** 只允许执行 findViewById 操作*/ protected abstract void initView() ; /** 执行注册监听、Adapter、广播,等解耦的操作*/ protected abstract void initListener(); /** 获取数据,初始化界面*/ protected abstract void initData(); /** 在 BaseActiviy 没有处理的点击事件,都在这个方法处理 */ protected abstract void processClick(View v); @Override public void onClick(View v) { switch (v.getId()){ case R.id.back://所有返回按钮的id名称都要设置为back finish(); break; default: processClick(v); break; } } /** 显示一个内容为 msg 的吐司*/ protected void toast(String msg){ Toast.makeText(BaseActivity.this, msg, Toast.LENGTH_SHORT).show(); } /** 打印一个等级为 error 的日志*/ protected void logE(String msg) { LogUtils.e(getClass(), msg); }}baseFragment
public abstract class BaseFragment extends Fragment implements View.OnClickListener{ private View root; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { root = inflater.inflate(getLayoutId(),null); initView(); initListener(); initData(); registerCommonBtn(); return root; } // 在多个界面都有的点击按钮,可以在这个方法注册监听 private void registerCommonBtn() { View view = findViewById(R.id.back); if (view != null){ view.setOnClickListener(this); } } /** 在当前Fragment使用的布局里查找控件*/ protected View findViewById(int id) { return root.findViewById(id); } /** 返回当前 Activity 使用的布局id*/ protected abstract int getLayoutId(); /** 只允许执行 findViewById 操作*/ protected abstract void initView() ; /** 执行注册监听、Adapter、广播,等解耦的操作*/ protected abstract void initListener(); /** 获取数据,初始化界面*/ protected abstract void initData(); /** 在 BaseActiviy 没有处理的点击事件,都在这个方法处理 */ protected abstract void processClick(View v); @Override public void onClick(View v) { switch (v.getId()){ case R.id.back: getFragmentManager().popBackStack(); break; default: processClick(v); break; } } /** 显示一个内容为 msg 的吐司*/ protected void toast(String msg){ Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show(); } /** 打印一个等级为 error 的日志*/ protected void logE(String msg) { LogUtils.e(getClass(), msg); }}
MainActivity
这里用到一个ViewCompat类
l ViewCompat它是v4支付库的一个类,可以向下兼容到android 1.6,api4,这个类是为了向下兼容3.0版本出来的那些属性动画
l ViewCompat的直接动画方法,无动画过渡效果 ViewCompat.setTranslationX(view, value);
l ViewCompat.animate()的动画方法,有动画过渡效果ViewCompat.animate().translationY()
public class MainActivity extends BaseActivity { private TextView tv_video; private TextView tv_audio; private View indicate; private ViewPager viewPager; private List<Fragment> fragmentList; private MainPagerAdapter mAdapter; /** * 返回当前 Activity 使用的布局id */ @Override protected int getLayoutId() { return R.layout.activity_main; } /** * 只允许执行 findViewById 操作 */ @Override protected void initView() { tv_video = (TextView) findViewById(R.id.main_tv_video); tv_audio = (TextView) findViewById(R.id.main_tv_audio); indicate = findViewById(R.id.main_indicate); viewPager = (ViewPager) findViewById(R.id.main_viewpager); } /** * 执行注册监听、Adapter、广播,等解耦的操作 */ @Override protected void initListener() { tv_video.setOnClickListener(this); tv_audio.setOnClickListener(this); fragmentList = new ArrayList<>(); mAdapter = new MainPagerAdapter(getSupportFragmentManager(), fragmentList); viewPager.setAdapter(mAdapter); viewPager.setOnPageChangeListener(new OnMainPageChangeListener()); } /** * 获取数据,初始化界面 */ @Override protected void initData() { fragmentList.add(new VideoListFragment()); fragmentList.add(new AudioListFragment()); mAdapter.notifyDataSetChanged(); // 高亮视频标签 updateTabs(0); // 初始化指示器宽度 int screenWidth = getWindowManager().getDefaultDisplay().getWidth(); indicate.getLayoutParams().width = screenWidth / fragmentList.size(); indicate.requestLayout(); } /** * 在 BaseActiviy 没有处理的点击事件,都在这个方法处理 * * @param v */ @Override protected void processClick(View v) { switch (v.getId()){ case R.id.main_tv_video: viewPager.setCurrentItem(0); break; case R.id.main_tv_audio: viewPager.setCurrentItem(1); break; } } // 根据选择的position位置,修改所有标题的高亮和缩放状态 private void updateTabs(int position) { updateTab(position, 0, tv_video); updateTab(position, 1, tv_audio); } // 根据 position 是否等于要比较的 position ,修改tab 的颜色和大小 private void updateTab(int position, int tabPosition, TextView tab) { if (position == tabPosition){ tab.setTextColor(getResources().getColor(R.color.green)); ViewCompat.animate(tab).scaleX(1.2f).scaleY(1.2f).setDuration(500).start(); }else { tab.setTextColor(getResources().getColor(R.color.halfwhite)); ViewCompat.animate(tab).scaleX(0.9f).scaleY(0.9f).setDuration(500).start(); } } private class OnMainPageChangeListener implements ViewPager.OnPageChangeListener { @Override // 在界面滚动时被调用 // position 当前选中的页面 // positionOffset 当前页面的偏移百分比 // positionOffsetPixels 当前页面偏移的像素值 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {// logE("OnMainPageChangeListener.onPageScrolled,position="+position+";positionOffset="+positionOffset+":positionOffsetPixels="+positionOffsetPixels);// 指示器移动到的位置 = 起始位置 + 偏移位置// 起始位置 = position * 指示器宽度// 偏移位置 = 屏幕偏移的百分比 * 指示器宽度 // 偏移位置 float offsetX = positionOffset * indicate.getWidth(); // 起始位置 int startX = position * indicate.getWidth(); // 指示器移动到的位置 float translationX = startX + offsetX; // 移动指示器 ViewCompat.setTranslationX(indicate, translationX); } @Override // 当选中的界面发生变化时被调用 public void onPageSelected(int position) {// logE("OnMainPageChangeListener.onPageSelected,position="+position); // 将被选中的标题修改为高亮颜色并放大,没选中的则变暗并缩小 updateTabs(position); } @Override // 当界面滚动状态改变时被调用 public void onPageScrollStateChanged(int state) {// logE("OnMainPageChangeListener.onPageScrollStateChanged,state="+state); } }}
MainPagerAdapter
public class MainPagerAdapter extends FragmentPagerAdapter { private List<Fragment> fragmentList; public MainPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) { super(fm); this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); }}
VideoPlayerActivity
查询数据库并展示的时候可以用CursorAdapter 他继承 BaseAdapter
里面封装了getCount() 和getItem()和getView()方法 只需要重写getView()里的两个抽象方法newView()和bindView().
查询数据库用到了系统提供的一个类 异步查询数据库AsyncQueryHandler
public class VideoListFragment extends BaseFragment { private ListView listView; private VideoListAdapter mAdapter; @Override protected int getLayoutId() { return R.layout.fragment_video_list; } @Override protected void initView() { listView = (ListView) findViewById(R.id.listview); } @Override protected void initListener() { mAdapter = new VideoListAdapter(getActivity(), null); listView.setAdapter(mAdapter); listView.setOnItemClickListener(new OnVideoItemClickListener()); } @Override protected void initData() { // 查询视频数据 ContentResolver resolver = getActivity().getContentResolver();// Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[]{Media._ID/*"uid as _id"*/, Media.DURATION, Media.TITLE, Media.SIZE, Media.DATA}, null, null, null);// CursorUtils.printCursor(cursor);// mAdapter.swapCursor(cursor); AsyncQueryHandler asyncQueryHandler = new MyAsyncQueryHandler(resolver); // token 可以用于区分不同类型的查询 // cookie 要使用 cursor数据的对象 asyncQueryHandler.startQuery( 0, mAdapter ,Media.EXTERNAL_CONTENT_URI, new String[]{Media._ID/*"uid as _id"*/, Media.DURATION, Media.TITLE, Media.SIZE, Media.DATA}, null, null, null); } @Override protected void processClick(View v) { } private class OnVideoItemClickListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 获取被选中的视频数据 Cursor cursor = (Cursor) mAdapter.getItem(position); VideoItem item = VideoItem.parserCursor(cursor);//解析cursor // 打开播放界面 Intent intent = new Intent(getActivity(), VideoPlayerActivity.class); intent.putExtra("videoItem",item);//将一个序列化的对象传递过去 startActivity(intent); } }}
public class MyAsyncQueryHandler extends AsyncQueryHandler {//这个类时异步处理查询数据库的 private static final String TAG = "MyAsyncQueryHandler"; public MyAsyncQueryHandler(ContentResolver cr) { super(cr); } @Override // 当子线程查询结束之后,会调用这个方法将 cursor传递过来 protected void onQueryComplete(int token, Object cookie, Cursor cursor) { LogUtils.e(TAG,"MyAsyncQueryHandler.onQueryComplete,"); CursorAdapter adapter = (CursorAdapter) cookie; adapter.swapCursor(cursor);//跟新列表数据 }}cursorAdapter
<span style="font-size:24px;">public class VideoListAdapter extends CursorAdapter { public VideoListAdapter(Context context, Cursor c) { super(context, c); } public VideoListAdapter(Context context, Cursor c, boolean autoRequery) { super(context, c, autoRequery); } public VideoListAdapter(Context context, Cursor c, int flags) { super(context, c, flags); } @Override // 创建新的View,并初始化ViewHolder public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = View.inflate(context, R.layout.video_item,null); ViewHolder holder = new ViewHolder(); holder.tv_title = (TextView) view.findViewById(R.id.video_item_tv_title); holder.tv_duration = (TextView) view.findViewById(R.id.video_item_tv_duration); holder.tv_size = (TextView) view.findViewById(R.id.video_item_tv_size); view.setTag(holder); return view; } @Override // 填充界面。cursor已经被移动到要获取数据的行 public void bindView(View view, Context context, Cursor cursor) { ViewHolder holder = (ViewHolder) view.getTag(); // 获取数据 String title = cursor.getString(cursor.getColumnIndex(Media.TITLE)); int duration = cursor.getInt(cursor.getColumnIndex(Media.DURATION)); long size = cursor.getLong(cursor.getColumnIndex(Media.SIZE)); // 填充内容 holder.tv_title.setText(title); holder.tv_duration.setText(StringUtils.formatTime(duration)); holder.tv_size.setText(Formatter.formatFileSize(context,size));; } private class ViewHolder{ TextView tv_title,tv_duration,tv_size; }}</span>解析cursor后得到的bean对象
public class VideoItem implements Serializable{ private String title; private int duration; private long size; private String path; // 解析 cursor 当前行的数据 public static VideoItem parserCursor(Cursor cursor){ VideoItem item = new VideoItem(); // 健壮性检查 if (cursor==null||cursor.getCount()==0){ return item; } item.title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE)); item.duration = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.DURATION)); item.size = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.SIZE)); item.path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA)); return item; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getDuration() { return duration; } public void setDuration(int duration) { this.duration = duration; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } @Override public String toString() { return "VideoItem{" + "title='" + title + '\'' + ", duration=" + duration + ", size=" + size + ", path='" + path + '\'' + '}'; }}
0 0
- 手机影音项目笔记(一)
- 手机影音项目笔记(二)-----视频播放处理
- 手机影音项目笔记(三)---音乐播放的处理
- 手机影音项目笔记(四)---音乐播放歌词的控件的自定义
- 手机影音
- Android 手机影音 开发过程记录(一)
- 练手项目一:手机安全卫士
- 项目笔记一
- 项目笔记(一)
- 项目笔记(一)
- 经网工具 3G影音助手-手机朋友的最爱
- Android 手机影音 开发过程记录(二)
- Android 手机影音 开发过程记录(三)
- Android 手机影音 开发过程记录(四)
- Android 手机影音 开发过程记录(五)
- Android 手机影音 开发过程记录(六)
- Android开发手机影音篇之软件结构分析
- C#手机应用工作笔记(一)
- Android Studio 常用快捷键 及常用使用技巧
- play框架用起来(3)
- latex学习笔记
- flask sqlalchemy(一)
- 上传本地代码到github
- 手机影音项目笔记(一)
- python之目录遍历
- Jaxb对XML的解析
- 关于UIView的回调方法
- navigationController侧滑返回上一页面(关闭本页面)失效的问题
- Swordsman
- 面向对象设计原则及设计模式概要
- IOS UDP使用
- 数据库事务及其特性