手机影音项目笔记(一)

来源:互联网 发布: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
原创粉丝点击