音乐项目总结笔记

1、不同界面间的跳转动画

Intent intent = new Intent(this, cla);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
//使用这个方法设置跳转动画
overridePendingTransition(R.anim.zoomin, R.anim.zoomout);
finish();

2、《隐私政策》字体颜色和点击事件实现

 字体颜色:首先是区分《隐私协议》和《用户手册》

//一大帕拉 String 内容
String privacyPolicyString = getResources().getString(R.string.privacy_policy_text);
//隐私协议
String privacyPolicy = getResources().getString(R.string.privacy_policy);
//用户协议
String userPolicy = getResources().getString(R.string.user_policy);
//字符下标
int indexPrivacy = privacyPolicyString.indexOf(privacyPolicy);
int indexUser = privacyPolicyString.indexOf(userPolicy);
//需要显示的字符串
SpannableString spannableString = new SpannableString(privacyPolicyString);
//设置点击字体颜色,必须声明两个对象,否则只会出现一个变色
ForegroundColorSpan colorSpan = new ForegroundColorSpan(getResources().getColor(R.color.colorTheme2));
ForegroundColorSpan colorSpan2 = new ForegroundColorSpan(getResources().getColor(R.color.colorTheme2));
spannableString.setSpan(colorSpan, indexPrivacy, indexPrivacy + privacyPolicy.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString.setSpan(colorSpan2, indexUser, indexUser + userPolicy.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
privacyText.setText(spannableString);
//下面这句必须使用使用,否则点击事件无效
privacyText.setMovementMethod(LinkMovementMethod.getInstance());

span点击事件学习参考参考连接

3、MVVM 中的VM(ViewModel使用总结)

保持VM是单例

//饿汉式 begin
public MusicModel(){}
public static MusicModel getInstance(){
    return MusicModelHoldr.instance;
}
private static class MusicModelHoldr{
    private static final MusicModel instance = new MusicModel();
}
//饿汉式 end

使用:(1)ViewModel中监听事件

private MutableLiveData<String> stringName= new MutableLiveData<>();
private LiveData<String> name= Transformations.map(stringName,
        new Function<String, String>() {
    @Override
    public String apply(String input) {
        return input;
    }
});
//使用get set获取对象

(2)在使用的地方监听,并改变UI

musicModel.getName().observe(this, new Observer<Boolean>() {
    @Override
    public void onChanged(String input) {
    }
});

4、应用导航栏使用

(1).先导入Navigation需要的框架,然后在需要的xml文件最下方添加组件信息,app:menu 是导航栏必须使用的属性,否则导航栏是空的。
NavigationView 需要包含在 DrawerLayout 之中。

<!--headerLayout:插入导航头部布局       -->
<!--menu        :导航界面具体项         -->
<!--layout_gravity:左边展开还是右边展开  -->
	<com.google.android.material.navigation.NavigationView
  	  android:layout_width="wrap_content"
  	  android:layout_height="match_parent"
  	  android:id="@+id/nav_controller_view_tag"
  	  android:layout_gravity="start"
  	  android:fitsSystemWindows="true"
  	  app:menu="@menu/activity_main_drawer"/>
  	  
</androidx.drawerlayout.widget.DrawerLayout>

(2)。DrawerLayout打开和关闭的方法

//左边打开
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()){
        case android.R.id.home://手机系统导航栏ID
            drawerLayout.openDrawer(GravityCompat.START);
            break;
   }
    return super.onOptionsItemSelected(item);
}
drawerLayout.closeDrawer(GravityCompat.START);//左边关闭

(3).设置 navigationView head_view 点击事件(在java中使用了navigationView.inflateHeaderView()方法加载头部布局,就不要在xml中再添加headLayout设置布局,否则会重复加载。

view = navigationView.inflateHeaderView(R.layout.nav_header_main);//head布局
imageHead = view.findViewById(R.id.image_head);//布局文件中的ImageView
signature = view.findViewById(R.id.textView);//布局文件中的TextView

(4).NavigationView的点击事件

//drawLayout 导航栏部分点击图标
navigationView.setNavigationItemSelectedListener(this)//navigation的点击事件
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item){}

5、Pop弹窗

initPopView();//初始化 popView 数据
//popView,需要弹出的组件,1080:弹出的高度
PopupWindow popupWindow = new PopupWindow(popView,
        ViewGroup.LayoutParams.MATCH_PARENT,
        1080,
        true);
popupWindow.setAnimationStyle(R.style.popwin_anim_style);
popupWindow.setOutsideTouchable(true);//触摸屏幕外是否会关闭
popupWindow.setTouchable(true);
//动画完毕后底部的位置
popupWindow.showAtLocation(viewContent,Gravity.BOTTOM,0,408);

/**
 * 初始化 popView 数据
 * @省略大部分代码,节约版面
 */
private void initPopView(){
    adapter = new MainPopListAdapter(MainActivity.this,audioInfoTables,MainPopListAdapter.NOMOREDATA);
    GridLayoutManager manager = new GridLayoutManager(MainActivity.this,1);
    curplaylist.setLayoutManager(manager);
    curplaylist.setAdapter(adapter);
}

6、注册广播

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BroadCastReceiveConstant.BROADCAST_SEND_AUDIO_INFO);
MusicInfoReceive receiver = new MusicInfoReceive();
MainActivity.this.registerReceiver(receiver,intentFilter);

7、返回键处理+时间判断

/**
 * 按返回键
 */
@Override
public void onBackPressed() {
    drawerLayout.closeDrawer(GravityCompat.START);
    if ((System.currentTimeMillis() - mExitTime) > 2000) {
        ToastShowUtil.showTextToast(getApplicationContext(), getString(R.string.back_tip));
        mExitTime = System.currentTimeMillis();
    }
}

8、动态权限请求

/**
 * 动态权限请求
 */
private void permissionsRequest() {
    PermissionX.init(this).permissions(
            //写入文件
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .onExplainRequestReason(new ExplainReasonCallbackWithBeforeParam() {
                @Override
                public void onExplainReason(ExplainScope scope, List<String> deniedList, boolean beforeRequest) {
                    scope.showRequestReasonDialog(deniedList, "即将申请的权限是程序必须依赖的权限", "我已明白");
                }
            })
            .onForwardToSettings(new ForwardToSettingsCallback() {
                @Override
                public void onForwardToSettings(ForwardScope scope, List<String> deniedList) {
                    scope.showForwardToSettingsDialog(deniedList, "您需要去应用程序设置当中手动开启权限", "我已明白");
                }
            })
            .setDialogTintColor(R.color.bottom_navigation_background_color, R.color.common_menu_background_color)
            .request(new RequestCallback() {
                @Override
                public void onResult(boolean allGranted, List<String> grantedList, List<String> deniedList) {
                    if (allGranted) {
                        //通过后的业务逻辑
                    } else {
                        ToastShowUtil.showTextToast(getApplicationContext(),"您拒绝了如下权限:" + deniedList);
                    }
                }
            });
}

9、DBFlow框架使用

学习链接:https://blog.csdn.net/jzman/article/details/80012837

10、从后台下载文件

this.mContext = context;
Request request = new Request.Builder()
        .url(url)
        .build();
client.newCall(request).enqueue(new Callback() {

    //下载失败
    @Override
    public void onFailure(Call call, IOException e) {
        download.error(e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        download.start(audioInfo);
        InputStream stream = null;
        byte[] bytes = new byte[2048];
        int len = 0;
        FileOutputStream fileOutputStream = null;
        String savePath = isExistDir(filePath);
        try{
            stream = response.body().byteStream();
            long total = response.body().contentLength();
            File file = new File(savePath,fileName+".mp3");
            fileOutputStream = new FileOutputStream(file);
            long sum = 0;
            while ((len = stream.read(bytes))!= -1){
                fileOutputStream.write(bytes,0,len);
                sum += len;
                //下载进入
                int progress = (int) (sum * 1.0f / total * 100);
                download.progress(progress);
            }
            fileOutputStream.flush();
            //下载完成可在下面定制操作
            download.finish(audioInfo,filePath + File.separator + fileName + ".mp3");
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (stream!= null){
                    stream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fileOutputStream != null){
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
});

判断文件是否存在

/**
 * 判断是否存在该文件夹
 * @param saveDir
 * @return
 */
private String isExistDir(String saveDir) throws IOException {
    File downloadFile = new File(saveDir);
    if (!downloadFile.mkdirs()) {
        downloadFile.createNewFile();
    }
    String savePath = downloadFile.getAbsolutePath();
    return savePath;
}

11、在AS中使用 网页

webView = root.findViewById(R.id.web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webView.getSettings().setLoadWithOverviewMode(true);
webView.loadUrl("file:///android_asset/manual.html");

12、酷狗音乐API

https://blog.csdn.net/qq_32551929/article/details/87256150
http://m.mamicode.com/info-detail-2817603.html
更多自己另找

13、select使用

也可以用图片

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/skin_kg_ic_playing_bar_playlist_queue_pressed" android:state_pressed="true" />
    <item android:drawable="@drawable/skin_kg_ic_playing_bar_playlist_queue_pressed" android:state_focused="true" />
    <item android:drawable="@drawable/skin_kg_ic_playing_bar_playlist_queue_default" />

</selector>

14、NavHostFragment使用

xml用使用fragment

<!-- 一般情况下使用 FrameLayout 设置碎片,这次模仿 Google 使用 fragment 添加碎片-->
<!-- defaultNavHost 和 navGraph 属性来自于 navigation 框架 -->
<!-- defaultNavHost : 是否设置 navigation 返回栈 -->
<!--     navGraph   : 绑定 navigation 文件 ( 需要创建 navigation 文件夹 )-->
<!-- 一定要配置 name 属性指定首发启动的fragment,否则会报 “ Error inflating class fragment ”-->
<!--    登陆 / 注册界面   -->
<fragment
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/nav_host_login_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:defaultNavHost="false"
    app:navGraph="@navigation/navigation_login"/>

创建navigation文件夹

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/navigation_fragment"
    app:startDestination="@id/fragment_search">

    <fragment android:id="@+id/fragment_search"
        android:name="com.example.music.fragment.SearchFragment"
        android:label="@string/bottom_navigation_search"
        tools:layout="@layout/fragment_search"/>

    <fragment android:id="@+id/fragment_my"
        android:name="com.example.music.fragment.MyFragment"
        android:label="@string/bottom_navigation_my"
        tools:layout="@layout/fragment_my"/>

</navigation>

在java中使用

controller = Navigation.findNavController(this,R.id.fragment);
NavigationUI.setupWithNavController(bottomNavigationView,controller);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
        R.id.fragment_search,R.id.fragment_my
).build();
//关联底部导航栏
NavigationUI.setupActionBarWithNavController(this,controller,appBarConfiguration);

15、刷新框架

<com.github.ybq.android.spinkit.SpinKitView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:padding="20dp"
    android:id="@+id/loading_img"
    style="@style/SpinKitView"
    app:SpinKit_Color="#FF0000"/>

16、Navigation一般使用

NavigationView navigationView = popView.findViewById(R.id.item_list);
navigationView.setNavigationItemSelectedListener(RankSongAdapter.this);

17、底部导航栏使用

<!-- 修改icon 和 title 可以通过创建 color 文件夹实现 -->
<!-- bottom navigation 背景默认主题为深色,设置背景颜色时不能呢使用透明度,否则会出现重影-->
<com.google.android.material.bottomnavigation.BottomNavigationView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:id="@+id/navigation_view"
    android:background="@color/bottom_navigation_background_color"
    app:menu="@menu/bottom_navigation_menu"
    app:itemIconTint="@color/bottom_navigation_icon_select"
    app:itemTextColor="@color/bottom_navigation_title_select"/>

itemIconTint 和 itemTextColor更换颜色

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!--实现自定义 bottom navigation 图片和标题颜色-->
    <item android:color="@color/bottom_navigation_select_icon_color" android:state_selected="true"/>
    <item android:color="@color/bottom_navigation_unSelect_icon_color" android:state_selected="false"/>

</selector>

18、常用框架

//导入ButterKnife框架
implementation 'com.jakewharton:butterknife:8.8.1'
//导入material 模式
implementation 'com.google.android.material:material:1.4.0'
//导入cardView
implementation 'androidx.cardview:cardview:1.0.0'
//导入底部导航 navigation 框架,实现碎片管理
implementation 'androidx.navigation:navigation-fragment:2.0.0'
implementation 'androidx.navigation:navigation-ui:2.0.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
//导入recycleView 框架
//noinspection GradleCompatible
implementation 'com.android.support:recyclerview-v7:30.0.0'
//导入 jsoup 框架
implementation 'org.jsoup:jsoup:1.13.1'
//Loading加载动画
implementation 'com.github.ybq:Android-SpinKit:1.2.0'
//下拉刷新框架
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0'
//banner轮播框架
implementation 'com.youth.banner:banner:1.4.9'
//图片缓存框架,提供流畅图片加载
implementation 'com.github.bumptech.glide:glide:4.5.0'
//导入okhttp框架
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'com.squareup.okio:okio:1.5.0'
//导入DBFlow数据库框架
annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:4.2.4"
implementation "com.github.Raizlabs.DBFlow:dbflow-core:4.2.4"
implementation "com.github.Raizlabs.DBFlow:dbflow:4.2.4"
//fastjson
implementation 'com.alibaba:fastjson:1.1.54.android'
//权限请求框架
implementation 'com.permissionx.guolindev:permissionx:1.4.0'
//greendao
implementation 'org.greenrobot:greendao:3.3.0'
implementation 'org.greenrobot:greendao-generator:3.3.0'
//跨线程/进程框架
implementation 'org.greenrobot:eventbus:3.1.1'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值