Fragment+ViewPager+TabLayout&EventBus&Banner&SD&SP
TabLayout
Tablayout继承自HorizontalScrollView,用作页面切换指示器,因使用简便功能强大而广泛使用在App中
TabLayout 的几个常用属性值
app:tabBackground 标签布局的背景色
app:tabIndicatorColor 指示器的颜色
app:tabIndicatorHeight 指示器的高度(如果不需要指示器可以设置为0dp)
app:tabMode 显示模式:默认 fixed(固定),scrollable(可横向滚动)
app:tabPadding 标签内边距
app:tabSelectedTextColor 标签选中的文本颜色
app:tabTextAppearance 标签文本样式
app:tabTextColor 标签未选中的文本颜色
Fragment+ViewPager+TabLayout结合使用:
xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tab_id"
app:tabSelectedTextColor="#E5AF35"
app:tabTextColor="#969696"
app:tabIndicatorColor="#E5AF35"
app:tabIndicatorHeight="5dp"
app:tabMode="scrollable"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vp_id"
android:layout_weight="8"
android:layout_width="match_parent"
android:layout_height="0dp">
</android.support.v4.view.ViewPager>
</LinearLayout>
MainActivity.java
package com.example.day007;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import com.example.day007.adapter.MyFragmentAdapter;
import com.example.day007.fragment.OneFragment;
import com.example.day007.fragment.TwoFragment;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private TabLayout tabId;
private ViewPager vpId;
private List<Fragment> list = new ArrayList<>();
private List<String> titles = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
tabId = findViewById(R.id.tab_id);
vpId = findViewById(R.id.vp_id);
list.add(new OneFragment());
list.add(new TwoFragment());
list.add(new OneFragment());
list.add(new TwoFragment());
titles.add("视频");
titles.add("新闻");
titles.add("图片");
titles.add("留言");
MyFragmentAdapter myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(), list, titles);
vpId.setAdapter(myFragmentAdapter);
//把viewPager和tabLayout绑定在一起,注释掉看看效果.
tabId.setupWithViewPager(vpId);
}
}
MyFragmentAdapter.java
package com.example.day007.adapter;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import java.util.ArrayList;
import java.util.List;
/**
* ${FENG}
* 2019-07-11
*/
public class MyFragmentAdapter extends FragmentStatePagerAdapter {
private List<Fragment> list;
private List<String> titles;
public MyFragmentAdapter(FragmentManager fm, List<Fragment> list, List<String> titles) {
super(fm);
this.list = list;
this.titles = titles;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Fragment getItem(int i) {
return list.get(i);
}
//返回与viewpage关联以后的tablayot的内容
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
EventBus
三个角色
Event:事件,它可以是任意类型,EventBus会根据事件类型进行全局的通知。
Subscriber:事件订阅者,在EventBus 3.0之前我们必须定义以onEvent开头的那几个方法,分别是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之后事件处理的方法名可以随意取,不过需要加上注解@subscribe,并且指定线程模型,默认是POSTING。
Publisher:事件的发布者,可以在任意线程里发布事件。一般情况下,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post(Object)方法即可。
四种线程模型
EventBus3.0有四种线程模型,分别是:
POSTING:默认,表示事件处理函数的线程跟发布事件的线程在同一个线程。
MAIN:表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
BACKGROUND:表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
ASYNC:表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
使用
依赖导包(Androidx)
implementation ‘org.greenrobot:eventbus:3.0.0’
用fragment接收eventbus代码
fragment
public class BlankFragment extends Fragment {
private TextView show;
public BlankFragment() {
// Required empty public constructor
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
// Inflate the layout for this fragment
View inflate = inflater.inflate(R.layout.fragment_blank, container, false);
show = inflate.findViewById(R.id.show);
return inflate;
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void getmsg(Message msg) {
String msg1 = msg.getMsg();
show.setText(msg1);
}
@Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().removeAllStickyEvents();
}
}
MainActivity
public class EvevtBus extends AppCompatActivity {
private EditText edit;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_evevt_bus);
edit = (EditText) findViewById(R.id.edit);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String msg = edit.getText().toString();
Message message = new Message(msg);
EventBus.getDefault().post(message);
}
});
}
}
Banner
使用
依赖&权限
导入依赖
compile ‘com.youth.banner:banner:1.4.10’
清单文件权限
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Bunner">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.youth.banner.Banner>
</LinearLayout>
外部类图片下载器
public class imgLoader extends ImageLoader {
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
Glide.with(context).load(path).into(imageView);
}
}
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bunner);
banner = (Banner) findViewById(R.id.banner);
//绑定下载器
banner.setImageLoader(new imgLoader());
//创建图片集合作为数据源
ArrayList<String> list = new ArrayList<>();
list.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571309316416&di=b25fb8a2fee660ae963a41c56c067cc6&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2F49c607dbba21551282e97ac4c71294373b4a488e.jpg");
list.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571309316412&di=f8e4ac3d1788a1419a961d169eac8504&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fc4f07739f34bc111ee50c84b2780a49d850b9cd5.jpg");
list.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571309316410&di=71bed840c95a5bd8a9dc4899526981bb&imgtype=0&src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farchive%2Fc65f0fb7343516425d1b0750094c111175a4cfb4.jpg");
list.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571309316406&di=ed83b7a2eb9c9d5ab90ed112d4912bd4&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F0%2F58a3c9d34cf61.jpg");
banner.setImages(list);
//设置banner样式
banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
//设置动画效果
banner.setBannerAnimation(Transformer.DepthPage);
//设置轮播间隔时间
banner.setDelayTime(1000);
//启动banner
banner.start();
}
}
SP
SharedPreferences
SharedPreferences简称Sp(后面都会称Sp),是一种轻量级的数据存储方式,采用Key/value的方式 进行映射,最终会在手机的/data/data/package_name/shared_prefs/目录下以xml的格式存在。
Sp通常用于记录一些参数配置、行为标记等!因为其使用简单,所以大多数开发者用起来很爽!
但是 请注意:千万不要使用Sp去存储量大的数据,也千万不要去让你的Sp文件超级大,否则会大大影响应用性能, 甚至出现ANR(程序无响应)
特点:
保存少量的数据,且这些数据的格式非常简单。 存储5种原始数据类型: boolean, float, int, long, String
比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),记住密码功能,音乐播放器播放模式。
技能要点: (1)如何存储数据 (2)如何获取数据
使用方式
**步骤1:**得到SharedPreferences对象 getSharedPreferences(“文件的名称”,“文件的类型”);
(1).Context.MODE_PRIVATE:指定该SharedPreferences数据只能被应用程序读写
(2)MODE_APPEND:检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
以下不在建议使用
(3).Context.MODE_WORLD_READABLE:指定该SharedPreferences数据能被其他
应用程序读,但不能写。
(4).Context,MODE_WORLD_WRITEABLE:指定该SharedPreferences数据能被其他应用程序写,但不能读。
**步骤2:**得到 SharedPreferences.Editor编辑对象
SharedPreferences.Editor editor=sp.edit();
**步骤3:**添加数据
editor.putBoolean(key,value)
editor.putString()
editor.putInt()
editor.putFloat()
editor.putLong()
**步骤4:**提交数据 editor.commit()或者apply()(推荐用这个.异步提交)
Editor其他方法: editor.clear() 清除数据 editor.remove(key) 移除指定key对应的数据
SD
四个方法展示SD卡储存
public class FileUtils {
//方法1:向SD卡中写json串
public static void write_json(String json) {
//判断是否挂载
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//获取SD卡根路径:mnt/shell/emulated/0
File file=Environment.getExternalStorageDirectory();
FileOutputStream out=null;
try {
//创建输出流
out= new FileOutputStream(new File(file,"json.txt"));
out.write(json.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//方法2:从SD卡中读取json串
public static String read_json() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = Environment.getExternalStorageDirectory();
FileInputStream inputStream = null;
StringBuffer sb=new StringBuffer();
try {
inputStream=new FileInputStream(new File(file,"json.txt"));
byte[] b=new byte[1024];
int len=0;
while((len=inputStream.read(b))!=-1){
sb.append(new String(b,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}else{
return "";
}
}
//方法3:从SD卡中读取一张图片
public static Bitmap read_bitmap(String filename) {//filename图片名字
Bitmap bitmap=null;
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File file=Environment.getExternalStorageDirectory();
File file1 = new File(file, filename);
//BitmapFactory可以直接根据SD卡图片路径转成一个bitmap对象
bitmap= BitmapFactory.decodeFile(file1.getAbsolutePath());
}
return bitmap;
}
//方法4:网络下载一张图片存储到SD卡中
public static void write_bitmap(String url) {//网址
new MyTask().execute(url);
}
static class MyTask extends AsyncTask<String,String,String> {
@Override
protected String doInBackground(String... strings) {
FileOutputStream out=null;
InputStream inputStream=null;//网络连接的输入流
HttpURLConnection connection=null;//向SD卡写的输出流
try {
URL url= new URL(strings[0]);
connection= (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5*1000);
connection.setReadTimeout(5*1000);
if (connection.getResponseCode()==200){
inputStream = connection.getInputStream();
//TODO 获取SD卡的路径
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//是否挂载
File file = Environment.getExternalStorageDirectory();
out = new FileOutputStream(new File(file,"xiaoyueyue.jpg"));
byte[] bytes=new byte[1024];
int len=0;
while((len=inputStream.read(bytes))!=-1){
out.write(bytes,0,len);
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关流
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(connection!=null){
connection.disconnect();
}
}
return null;
}
}
}