阅读原文
01-splash页面
public class SplashActivity extends AppCompatActivity
{
private static final String TAG = SplashActivity.class.getSimpleName();//"SplashActivity"
private boolean isStartMain = false;//是否进入主界面标志
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
handler.postDelayed(new Runnable()
{
@Override
public void run()
{
//两秒后才执行到这里
//执行在主线程中
startMainActivity();
Log.e(TAG, "当前线程名称==" + Thread.currentThread().getName());
}
}, 2000);
}
/**
* 跳转到主页面,并且把当前页面关闭掉
*/
private void startMainActivity()
{
if (!isStartMain)
{
isStartMain = true;
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
//关闭当前页面
finish();
}
}
/**
* 有一个bug,启动了多次Activity,如何解决?
* 1.设置为启动的Activity只能是单例。
* 在功能清单文件android:launchMode="singleTask"
* 2.从源头上控制,执行代码只一次
*/
@Override
public boolean onTouchEvent(MotionEvent event)
{
Log.e(TAG, "onTouchEvent==Action" + event.getAction());
startMainActivity();
return super.onTouchEvent(event);
}
@Override
protected void onDestroy()
{
//把所有的消息和回调移除
handler.removeCallbacksAndMessages(null);
super.onDestroy();
}
}
02-MainActivity主页面布局
2.1activity_main.xml
2.2样式中引用如下
2.3RadioButton文字颜色
rb_bottom_textcolor_selector.xml
03-基类BasePager
public abstract class BasePager
{
/**
* 上下文
*/
public final Context context;
/**
* 接收各个页面的实例
*/
public View rootView;
public boolean isInitData;
public BasePager(Context context)
{
this.context = context;
rootView = initView();
}
/**
* 强制子页面实现该方法,实现想要的特定的效果
*
* @return
*/
public abstract View initView();
/**
* 当子页面,需要绑定数据,或者联网请求数据并且绑定的时候,重写该方法
*/
public void initData()
{
}
}
04-监听RadioGroup的状态
4.1 在MainActivity的onCreate方法中初始化各个页面
private RadioGroup rg_bottom_tag;
private Fragment fragment;
/**
* 页面的集合
*/
private ArrayList basePagers;
/**
* 选中的位置
*/
private int position;
/**
* 初始化各个页面
*/
pbasePagers = new ArrayList<>();
basePagers.add(new VideoPager(this));//添加本地视频页面-0
basePagers.add(new AudioPager(this));//添加本地音乐页面-1
basePagers.add(new NetVideoPager(this));//添加网络视频页面-2
basePagers.add(new NetAudioPager(this));//添加网络音频页面-3
//设置RadioGroup的监听
rg_bottom_tag.setOnCheckedChangeListener(new MyOnCheckedChangeListener());
rg_bottom_tag.check(R.id.rb_video);//默认选中首页
4.2 MyOnCheckedChangeListener
class MyOnCheckedChangeListener implements RadioGroup.OnCheckedChangeListener
{
@Override
public void onCheckedChanged(RadioGroup group, int checkedId)
{
switch (checkedId)
{
default:
position = 0;
break;
case R.id.rb_audio://音频
position = 1;
break;
case R.id.rb_net_video://网络视频
position = 2;
break;
case R.id.rb_netaudio://网络音频
position = 3;
break;
}
setFragment();
}
}
4.3设置不同页面
/**
* 把页面添加到Fragment中
*/
private void setFragment()
{
//1.得到FragmentManger
FragmentManager manager = getSupportFragmentManager();
//2.开启事务
FragmentTransaction ft = manager.beginTransaction();
//3.替换
ft.replace(R.id.fl_main_content, new Fragment()
{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
BasePager basePager = getBasePager();
if (basePager != null)
{
//各个页面的视图
return basePager.rootView;
}
return null;
}
});
//4.提交事务
ft.commit();
}
/**
* 根据位置得到对应的页面
*
* @return
*/
private BasePager getBasePager()
{
BasePager basePager = basePagers.get(position);
if (basePager != null && !basePager.isInitData)
{
basePager.initData();//联网请求或者绑定数据
basePager.isInitData = true;
}
return basePager;
}
05-屏蔽各个页面重复初始化数据
5.1在主页面中屏蔽
if (basePager != null && !basePager.isInitData)
{
basePager.initData();//联网请求或者绑定数据
basePager.isInitData = true;
}
06-本地视频列表VideoPager
6.1 顶部标题栏布局
6.2 自定义的顶部标题栏点击事件
public class TitleBar extends LinearLayout implements View.OnClickListener
{
private View tv_search;
private View rl_game;
private View iv_record;
private Context context;
/**
* 在代码中实例化该类的时候使用这个方法
*
* @param context
*/
public TitleBar(Context context)
{
this(context, null);
}
/**
* 当在布局文件使用该类的时候,Android系统通过这个构造方法实例化该类
*
* @param context
* @param attrs
*/
public TitleBar(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
/**
* 当需要设置样式的时候,可以使用该方法
*
* @param context
* @param attrs
* @param defStyleAttr
*/
public TitleBar(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
this.context = context;
}
/**
* 当布局文件加载完成的时候回调这个方法
*/
@Override
protected void onFinishInflate()
{
super.onFinishInflate();
//得到孩子的实例
tv_search = getChildAt(1);
rl_game = getChildAt(2);
iv_record = getChildAt(3);
//设置点击事件
tv_search.setOnClickListener(this);
rl_game.setOnClickListener(this);
iv_record.setOnClickListener(this);
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.tv_search://搜索
Toast.makeText(context, "搜索", Toast.LENGTH_SHORT).show();
break;
case R.id.rl_game://游戏
Toast.makeText(context, "游戏", Toast.LENGTH_SHORT).show();
break;
case R.id.iv_record://播放历史
Toast.makeText(context, "播放历史", Toast.LENGTH_SHORT).show();
break;
}
}
}
6.3 视频列表显示
6.3.1 视频列表的布局文件
6.3.2 得到手机里面的视频和屏幕3MB以下视频
/**
* 从本地的sdcard得到数据
* //1.遍历sdcard,后缀名
* //2.从内容提供者里面获取视频
* //3.如果是6.0的系统,动态获取读取sdcard的权限
*/
private void getDataFromLocal()
{
new Thread(new Runnable()
{
@Override
public void run()
{
//SystemClock.sleep(2000);延迟2s加载
isGrantExternalRW((Activity) context);
mediaItems = new ArrayList();
ContentResolver contentResolver = context.getContentResolver();
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] objs =
{
MediaStore.Video.Media.DISPLAY_NAME,//视频文件在sdcard的名称
MediaStore.Video.Media.DURATION,//视频总时长
MediaStore.Video.Media.SIZE,//视频的文件大小
MediaStore.Video.Media.DATA,//视频的绝对地址
MediaStore.Video.Media.ARTIST,//歌曲的演唱者
};
Cursor cursor = contentResolver.query(uri, objs, null, null, null);
if (cursor != null)
{
while (cursor.moveToNext())
{
MediaItem mediaItem = new MediaItem();
mediaItems.add(mediaItem);//写在上面
String name = cursor.getString(0);//视频的名称
mediaItem.setName(name);
long duration = cursor.getLong(1);//视频的时长
mediaItem.setDuration(duration);
long size = cursor.getLong(2);//视频的文件大小
mediaItem.setSize(size);
String data = cursor.getString(3);//视频的播放地址
mediaItem.setData(data);
String artist = cursor.getString(4);//艺术家
mediaItem.setArtist(artist);
}
cursor.close();//释放
}
//Handler发消息
handler.sendEmptyMessage(10);
}
}).start();
}
6.3.3 视频显示出来
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
if (mediaItems != null && mediaItems.size() > 0)
{
//有数据
//设置适配器
videoPagerAdapter = new VideoPagerAdapter(context, mediaItems,false);
listview.setAdapter(videoPagerAdapter);
//把文本隐藏
tvNomedia.setVisibility(View.GONE);
}
else
{
//没有数据
//文本显示
tvNomedia.setVisibility(View.VISIBLE);
}
//ProgressBar隐藏
pbLoading.setVisibility(View.GONE);
}
};
6.3.4 适配器
/**
* VideoPager的适配器
*/
public class VideoPagerAdapter extends BaseAdapter
{
private Context context;
private final boolean isVideo;
private final ArrayList mediaItems;
private Utils utils;
public VideoPagerAdapter(Context context, ArrayList mediaItems,boolean isVideo)
{
this.context = context;
this.mediaItems = mediaItems;
this.isVideo = isVideo;
utils = new Utils();
}
@Override
public int getCount()
{
return mediaItems.size();
}
@Override
public Object getItem(int position)
{
return null;
}
@Override
public long getItemId(int position)
{
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder;
if (convertView == null)
{
convertView = View.inflate(context, R.layout.item_video_pager, null);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
//根据position得到列表中对应位置的数据
MediaItem mediaItem = mediaItems.get(position);
viewHolder.tvName.setText(mediaItem.getName());
viewHolder.tvSize.setText(Formatter.formatFileSize(context, mediaItem.getSize()));
viewHolder.tvTime.setText(utils.stringForTime((int) mediaItem.getDuration()));
return convertView;
}
static class ViewHolder
{
@Bind(R.id.iv_icon)
ImageView ivIcon;
@Bind(R.id.tv_name)
TextView tvName;
@Bind(R.id.tv_time)
TextView tvTime;
@Bind(R.id.tv_size)
TextView tvSize;
ViewHolder(View view)
{
ButterKnife.bind(this, view);
}
}
}
6.4 视频列表的Item完成和相关数据处理
6.4.1 item_video_pager.xml
07-播放器的控制面板
7.1 播放器控制栏顶部
7.2 系统播放器布局
08-视频seekBar进度更新
8.1 设置总时间和seeKBar的总长度,在准备好了的回调中设置
int duration = videoview.getDuration();
//把毫秒转换成 12:22.40
tv_duration.setText(utils.stringForTime(duration));
//设置视频的总长度为video_seekBar的多少等分
video_seekBar.setMax(duration);
//发消息开始更新
handler.sendEmptyMessage(PROGRESS);
09-实现视频的拖动
class VideoOnSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener
{
/**
* 当手指滑动的时候,会引起SeekBar进度变化,会回调这个方法
*
* @param seekBar
* @param progress
* @param fromUser 如果是用户引起的true,不是用户引起的false
*/
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
if (fromUser)
{
videoview.seekTo(progress);
}
}
/**
* 当手指触碰的时候回调这个方法
*
* @param seekBar
*/
@Override
public void onStartTrackingTouch(SeekBar seekBar)
{
handler.removeMessages(HIDE_MEDIACONTROLLER);
}
/**
* 当手指离开的时候回调这个方法
*
* @param seekBar
*/
@Override
public void onStopTrackingTouch(SeekBar seekBar)
{
handler.sendEmptyMessageDelayed(HIDE_MEDIACONTROLLER, 4000);
}
}
//设置SeeKbar状态变化的监听
seekbarVideo.setOnSeekBarChangeListener(new VideoOnSeekBarChangeListener());
010-设置电池状态
10.1 监听电量变化广播
utils = new Utils();
//注册电量广播
receiver = new MyReceiver();
IntentFilter intentFiler = new IntentFilter();
//当电量变化的时候发这个广播
intentFiler.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, intentFiler);
class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
int level = intent.getIntExtra("level", 0);//0~100;
setBattery(level);
}
}
10.2电量刷新方法
/**
* 设置电量的状态
*/
private void setBattery(int level)
{
if (level <= 0)
{
ivBattery.setImageResource(R.drawable.ic_battery_0);
}
else if (level <= 10)
{
ivBattery.setImageResource(R.drawable.ic_battery_10);
}
else if (level <= 20)
{
ivBattery.setImageResource(R.drawable.ic_battery_20);
}
else if (level <= 40)
{
ivBattery.setImageResource(R.drawable.ic_battery_40);
}
else if (level <= 60)
{
ivBattery.setImageResource(R.drawable.ic_battery_60);
}
else if (level <= 80)
{
ivBattery.setImageResource(R.drawable.ic_battery_80);
}
else if (level <= 100)
{
ivBattery.setImageResource(R.drawable.ic_battery_100);
}
else
{
ivBattery.setImageResource(R.drawable.ic_battery_100);
}
}
11-得到系统时间并且更新显示
11.1得到系统时间
/**
* 得到系统时间
*
* @return
*/
private String getSysteTime()
{
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
return format.format(new Date());
}
11.2在hanlder设置更新
//设置系统时间
tv_system_time.setText(utils.getSystemTime());