From 7364d3500cbb90a943494827077bfc0357ac4a8c Mon Sep 17 00:00:00 2001 From: Yutousama <583819556@qq.com> Date: Wed, 25 Nov 2020 02:20:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=9C=80=E8=A6=81=E6=98=AF?= =?UTF-8?q?=E4=B9=B1=E5=BA=8F=20Fragment=E6=9C=89=E6=B3=84=E9=9C=B2?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20=E6=96=B0=E5=A2=9E=E4=BA=86Kotlin=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BD=86=E4=BB=85=E4=BB=85=E5=8F=AA=E6=98=AF?= =?UTF-8?q?=E4=B8=BA=E4=BA=86Helpers=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 30 ++- .../Adapters/MusicLibsAdapter.java | 230 ++++++++++++++++++ .../nas_music_player/Datas/MusicData.java | 29 +++ .../containers/MediaBrowserHelper.java | 27 +- .../containers/MusicContainer.java | 53 +++- .../nas_music_player/tools/AppTools.java | 29 ++- .../yutou/nas_music_player/tools/Helpers.kt | 20 ++ .../views/Fragments/MusicLibsFragment.java | 60 +++++ .../nas_music_player/views/MainActivity.java | 29 ++- .../views/PlayLibsActivity.java | 127 ++++++++-- app/src/main/res/drawable-v24/ic_dir.png | Bin 0 -> 1316 bytes app/src/main/res/drawable-v24/ic_list.png | Bin 0 -> 1454 bytes app/src/main/res/drawable/ic_collection.png | Bin 0 -> 1710 bytes app/src/main/res/drawable/ic_dislike.png | Bin 0 -> 2426 bytes app/src/main/res/drawable/ic_hi_res.png | Bin 0 -> 22562 bytes app/src/main/res/drawable/ic_top.png | Bin 0 -> 994 bytes app/src/main/res/layout/activity_main.xml | 9 +- .../main/res/layout/fragment_music_libs.xml | 11 + .../res/layout/layout_music_libs_item.xml | 115 +++++++++ app/src/main/res/layout/layout_play.xml | 161 ++++++------ build.gradle | 5 + gradle.properties | 4 +- 22 files changed, 821 insertions(+), 118 deletions(-) create mode 100644 app/src/main/java/com/yutou/nas_music_player/Adapters/MusicLibsAdapter.java create mode 100644 app/src/main/java/com/yutou/nas_music_player/tools/Helpers.kt create mode 100644 app/src/main/java/com/yutou/nas_music_player/views/Fragments/MusicLibsFragment.java create mode 100644 app/src/main/res/drawable-v24/ic_dir.png create mode 100644 app/src/main/res/drawable-v24/ic_list.png create mode 100644 app/src/main/res/drawable/ic_collection.png create mode 100644 app/src/main/res/drawable/ic_dislike.png create mode 100644 app/src/main/res/drawable/ic_hi_res.png create mode 100644 app/src/main/res/drawable/ic_top.png create mode 100644 app/src/main/res/layout/fragment_music_libs.xml create mode 100644 app/src/main/res/layout/layout_music_libs_item.xml diff --git a/app/build.gradle b/app/build.gradle index 3af6eee..9e47798 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,17 @@ -apply plugin: 'com.android.application' +plugins { + id 'com.android.application' + id 'kotlin-android' +} android { + signingConfigs { + yutou { + storeFile file('D:\\AndroidKeys\\yutou.jks') + storePassword '34864394' + keyAlias 'yutou' + keyPassword '34864394' + } + } compileSdkVersion 30 buildToolsVersion "30.0.2" @@ -20,21 +31,30 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } } dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.work:work-runtime:2.4.0' - testImplementation 'junit:junit:4.12' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + testImplementation 'junit:junit:4.13.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.co.cyberagent.android:gpuimage:2.1.0' - implementation 'com.alibaba:fastjson:1.1.72.android' + implementation 'com.alibaba:fastjson:1.2.68' //noinspection GradleCompatible implementation 'com.android.support:support-media-compat:28.0.0' implementation 'androidx.palette:palette:1.0.0' @@ -43,5 +63,9 @@ dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.5' implementation 'com.kaopiz:kprogresshud:1.2.0' implementation 'com.ogaclejapan.smarttablayout:library:2.0.0@aar' + implementation 'com.ogaclejapan.smarttablayout:utils-v4:2.0.0@aar' + implementation 'com.github.promeg:tinypinyin:2.0.3' + implementation 'com.github.myinnos:AlphabetIndex-Fast-Scroll-RecyclerView:1.0.95' + implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' } \ No newline at end of file diff --git a/app/src/main/java/com/yutou/nas_music_player/Adapters/MusicLibsAdapter.java b/app/src/main/java/com/yutou/nas_music_player/Adapters/MusicLibsAdapter.java new file mode 100644 index 0000000..504c911 --- /dev/null +++ b/app/src/main/java/com/yutou/nas_music_player/Adapters/MusicLibsAdapter.java @@ -0,0 +1,230 @@ +package com.yutou.nas_music_player.Adapters; + +import android.annotation.SuppressLint; +import android.util.ArrayMap; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.SectionIndexer; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.github.promeg.pinyinhelper.Pinyin; +import com.yutou.nas_music_player.Datas.MusicData; +import com.yutou.nas_music_player.MyApplication; +import com.yutou.nas_music_player.R; +import com.yutou.nas_music_player.containers.MusicContainer; +import com.yutou.nas_music_player.tools.AppData; +import com.yutou.nas_music_player.tools.AppTools; +import com.yutou.nas_music_player.tools.Helpers; +import com.yutou.nas_music_player.tools.StringUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import cc.ibooker.ztextviewlib.MarqueeTextView; +import jp.wasabeef.glide.transformations.RoundedCornersTransformation; + +public class MusicLibsAdapter extends RecyclerView.Adapter implements SectionIndexer { + public static final int LIBS_MODEL_ALL=0; + public static final int LIBS_MODEL_Album=1; + public static final int LIBS_MODEL_Artist=2; + public static final int LIBS_MODEL_Tmp=3; + public static final int LIBS_MODEL_PLAY_LIST=4; + public static final int LIBS_MODEL_PLAY_Collection=5; + private LinkedHashMap> musicDataList; + + private String mSections = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#"; + private HashMap sectionsTranslator = new HashMap<>(); + private ArrayList mSectionPositions; + private ArrayList mSectionPositionsKey; + public MusicLibsAdapter(int model){ + initData(model); + } + private int model=-1; + public void initData(int model){ + this.model=model; + System.out.println("填充序列 设置model "+model); + List tmp=new ArrayList<>(); + switch (model){ + case LIBS_MODEL_Album: + musicDataList= MusicContainer.getInstance().getAllAlbumMapList(); + break; + case LIBS_MODEL_Artist: + musicDataList=MusicContainer.getInstance().getAllArtistMapList(); + break; + case LIBS_MODEL_Tmp: + tmp=MusicContainer.getInstance().getTmpPlayList(); + musicDataList=new LinkedHashMap<>(); + musicDataList.put("list",tmp); + break; + case LIBS_MODEL_PLAY_LIST: + tmp=MusicContainer.getInstance().getPlayList(); + musicDataList=new LinkedHashMap<>(); + musicDataList.put("list",tmp); + break; + case LIBS_MODEL_PLAY_Collection: + tmp=new ArrayList<>(); + musicDataList=new LinkedHashMap<>(); + musicDataList.put("list",tmp); + break; + case LIBS_MODEL_ALL: + default: + tmp=MusicContainer.getLibs().getMainData(); + musicDataList=new LinkedHashMap<>(); + musicDataList.put("list",tmp); + } + } + @Override + public Object[] getSections() { + List sections = new ArrayList<>(27); + mSectionPositions = new ArrayList<>(); + mSectionPositionsKey = new ArrayList<>(); + System.out.println("填充序列:"+musicDataList.size()+" "+model+" "+musicDataList.containsKey("list")); + if(musicDataList.containsKey("list")){ + List list=musicDataList.get("list"); + for (int i = 0; i < list.size(); i++) { + String section= Pinyin.toPinyin(list.get(i).getTitle().charAt(0)).substring(0,1).toUpperCase(); + if (!sections.contains(section)) { + sections.add(section); + System.out.println(section); + mSectionPositions.add(i); + } + } + }else { + /* Iterator iterator=musicDataList.keySet().iterator(); + int i=0; + while (iterator.hasNext()){ + String key=iterator.next(); + if(StringUtil.isEmpty(key)){ + key="#"; + } + String section= Pinyin.toPinyin(key.charAt(0)).toUpperCase(); + if (!sections.contains(section)) { + sections.add(section); + mSectionPositions.add(i); + } + i++; + }*/ + int i=0; + for (String key : musicDataList.keySet()) { + if(StringUtil.isEmpty(key)){ + key="#"; + } + mSectionPositionsKey.add(key); + String section=Pinyin.toPinyin(key.charAt(0)).substring(0,1).toUpperCase(); + System.out.println(section); + if (!sections.contains(section)) { + + sections.add(section); + mSectionPositions.add(i); + } + i++; + } + } + ArrayList alphabetFull = new ArrayList<>(Arrays.asList(Pinyin.toPinyin(mSections, ",").split(","))); + sectionsTranslator = Helpers.Companion.sectionsHelper(sections, alphabetFull); + + return alphabetFull.toArray(new String[0]); + } + + @Override + public int getPositionForSection(int i) { + return mSectionPositions.get(sectionsTranslator.get(i)); + } + + @Override + public int getSectionForPosition(int i) { + return i; + } + + + @NonNull + @Override + public MusicLibsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.layout_music_libs_item, parent, false); + return new ViewHolder(v); + } + + @SuppressLint("SetTextI18n") + @Override + public void onBindViewHolder(@NonNull MusicLibsAdapter.ViewHolder holder, int position) { + System.out.println("填充数据?"+position); + if(musicDataList.containsKey("list")){ + List list=musicDataList.get("list"); + MusicData data=list.get(position); + holder.title.setText(data.getTitle()); + holder.artist.setText(data.getArtist()); + if(!data.isDir()){ + holder.message.setText(data.getBitRate() + "kbps | " + data.getSampleRate() + "hz | "+data.getEncodingType() ); + holder.icon.setImageBitmap(data.getImg()); + }else{ + holder.message.setText(""); + holder.icon.setImageResource(R.drawable.ic_dir); + } + }else{ + System.out.println(mSectionPositionsKey.size()+" "+musicDataList.size()); + String key=mSectionPositionsKey.get(position); + if(musicDataList.containsKey(key)) { + MusicData data = musicDataList.get(key).get(0); + holder.title.setText(data.getAlbum()); +// holder.icon.setImageBitmap(data.getImg()); + holder.artist.setVisibility(View.GONE); + holder.message.setVisibility(View.GONE); + AppData.handler.post(new Runnable() { + @Override + public void run() { + Glide.with(MyApplication.application).load(data.getImg()) + .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(25, 3))) + .into(holder.icon); + } + }); + } + /* for (String title : musicDataList.keySet()) { + MusicData data=musicDataList.get(title).get(0); + holder.icon.setImageBitmap(data.getImg()); + holder.title.setText(title); + holder.artist.setVisibility(View.GONE); + holder.message.setVisibility(View.GONE); + }*/ + } + } + + @Override + public int getItemCount() { + if(musicDataList.containsKey("list")){ + return musicDataList.get("list").size(); + } + return musicDataList.keySet().size(); + } + static class ViewHolder extends RecyclerView.ViewHolder { + MarqueeTextView title,artist,message; + LinearLayout buttons; + ImageButton collection,top,dislike; + ImageView icon; + + ViewHolder(View itemView) { + super(itemView); + title=itemView.findViewById(R.id.title); + artist=itemView.findViewById(R.id.artist); + message=itemView.findViewById(R.id.message); + buttons=itemView.findViewById(R.id.buttons); + collection=itemView.findViewById(R.id.collection); + top=itemView.findViewById(R.id.top); + dislike=itemView.findViewById(R.id.dislike); + icon=itemView.findViewById(R.id.album_image); + } + } +} diff --git a/app/src/main/java/com/yutou/nas_music_player/Datas/MusicData.java b/app/src/main/java/com/yutou/nas_music_player/Datas/MusicData.java index 08ecf46..964d3ad 100644 --- a/app/src/main/java/com/yutou/nas_music_player/Datas/MusicData.java +++ b/app/src/main/java/com/yutou/nas_music_player/Datas/MusicData.java @@ -280,4 +280,33 @@ public class MusicData { public void setMd5(String md5) { this.md5 = md5; } + + @Override + public String toString() { + return "MusicData{" + + "artist='" + artist + '\'' + + ", album='" + album + '\'' + + ", title='" + title + '\'' + + ", comment='" + comment + '\'' + + ", year='" + year + '\'' + + ", track='" + track + '\'' + + ", disc_no='" + disc_no + '\'' + + ", composer='" + composer + '\'' + + ", artist_sort='" + artist_sort + '\'' + + ", lastDir='" + lastDir + '\'' + + ", file='" + file + '\'' + + ", isDir=" + isDir + + ", img=" + img + + ", bitRate=" + bitRate + + ", sampleRate=" + sampleRate + + ", noOfSamples=" + noOfSamples + + ", channelCount=" + channelCount + + ", encodingType='" + encodingType + '\'' + + ", durationAsDouble=" + durationAsDouble + + ", lossless=" + lossless + + ", variableBitRate=" + variableBitRate + + ", md5='" + md5 + '\'' + + ", isDownloadImg=" + isDownloadImg + + '}'; + } } diff --git a/app/src/main/java/com/yutou/nas_music_player/containers/MediaBrowserHelper.java b/app/src/main/java/com/yutou/nas_music_player/containers/MediaBrowserHelper.java index f1a9b50..e874536 100644 --- a/app/src/main/java/com/yutou/nas_music_player/containers/MediaBrowserHelper.java +++ b/app/src/main/java/com/yutou/nas_music_player/containers/MediaBrowserHelper.java @@ -10,7 +10,6 @@ import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import com.yutou.nas_music_player.services.MusicService; -import com.yutou.nas_music_player.views.MainActivity; import java.util.ArrayList; import java.util.List; @@ -27,32 +26,39 @@ public class MediaBrowserHelper { this.context = context; browserConnectionCallback = new MediaBrowserConnectionCallback(); controllerCallback = new MediaControllerCallback(); - subscriptionCallback=new MediaBrowserSubscriptionCallback(); + subscriptionCallback = new MediaBrowserSubscriptionCallback(); mMediaBrowser = new MediaBrowserCompat(context, new ComponentName(context, MusicService.class), browserConnectionCallback, null); mMediaBrowser.connect(); - MusicContainer.getInstance().setBrowserHelper(this); + MusicContainer.getInstance().addBrowserHelper(this); } - public void onStop(){ - if(controllerCompat!=null){ + + public void onStop() { + if (controllerCompat != null) { controllerCompat.unregisterCallback(controllerCallback); } - if(mMediaBrowser!=null&&mMediaBrowser.isConnected()){ + if (mMediaBrowser != null && mMediaBrowser.isConnected()) { mMediaBrowser.disconnect(); - mMediaBrowser=null; + mMediaBrowser = null; } + MusicContainer.getInstance().removeBrowserHelper(this); } - public boolean isPlayer(){ + + public boolean isPlayer() { return MusicContainer.getInstance().getMediaPlayer().isPlaying(); } + public MediaControllerCompat.TransportControls getTransportControls() { - if(controllerCompat==null) + if (controllerCompat == null) return null; return controllerCompat.getTransportControls(); } - private List callbacks=new ArrayList<>(); + + private List callbacks = new ArrayList<>(); + public void regPlayListener(MediaControllerCompat.Callback playListener) { callbacks.add(playListener); } + private class MediaBrowserConnectionCallback extends MediaBrowserCompat.ConnectionCallback { @Override public void onConnected() { @@ -105,6 +111,7 @@ public class MediaBrowserHelper { } } } + public class MediaBrowserSubscriptionCallback extends MediaBrowserCompat.SubscriptionCallback { } diff --git a/app/src/main/java/com/yutou/nas_music_player/containers/MusicContainer.java b/app/src/main/java/com/yutou/nas_music_player/containers/MusicContainer.java index 9e3722b..c2696cc 100644 --- a/app/src/main/java/com/yutou/nas_music_player/containers/MusicContainer.java +++ b/app/src/main/java/com/yutou/nas_music_player/containers/MusicContainer.java @@ -18,6 +18,7 @@ import com.yutou.nas_music_player.tools.StringUtil; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Random; @@ -39,9 +40,10 @@ public class MusicContainer { private MusicData nowPlayData = null; private MusicLibsInitInterface initInterface; private List completionListener; - private MediaBrowserHelper browserHelper; + private List browserHelpers; private List playList, tmpList; - private Map> albumMapList; + private LinkedHashMap> albumMapList; + private LinkedHashMap> artistMapList; private int playModel = PLAY_MODEL_RANDOM; private PreviousPlayerList previousPlayerList; @@ -50,8 +52,10 @@ public class MusicContainer { mediaPlayer = new MediaPlayer(); playList = new ArrayList<>(); tmpList = new ArrayList<>(); - albumMapList = new HashMap<>(); + albumMapList = new LinkedHashMap<>(); + artistMapList = new LinkedHashMap<>(); previousPlayerList = new PreviousPlayerList(); + browserHelpers=new ArrayList<>(); playIndex = ConfigTools.getPreferences().getInt("playIndex", 0); initMediaPlayer(); libs = new MusicLibs(); @@ -78,7 +82,9 @@ public class MusicContainer { System.out.println("自动播放完成,进行下一曲"); playTimer.cancel(); playTimer = null; - browserHelper.getTransportControls().skipToNext(); + for (MediaBrowserHelper browserHelper : browserHelpers) { + browserHelper.getTransportControls().skipToNext(); + } } } }); @@ -113,8 +119,11 @@ public class MusicContainer { this.nowPlayData = musicData; } - public void setBrowserHelper(MediaBrowserHelper browserHelper) { - this.browserHelper = browserHelper; + public void addBrowserHelper(MediaBrowserHelper browserHelper) { + browserHelpers.add(browserHelper); + } + public void removeBrowserHelper(MediaBrowserHelper browserHelper){ + browserHelpers.remove(browserHelper); } public static MusicContainer getInstance() { @@ -335,6 +344,16 @@ public class MusicContainer { } return libs.mainData; } + public List getTmpPlayList(){ + return tmpList; + } + public LinkedHashMap> getAllAlbumMapList(){ + return albumMapList; + } + public LinkedHashMap> getAllArtistMapList(){ + return artistMapList; + } + public class MusicLibs { private List mainData; @@ -364,6 +383,7 @@ public class MusicContainer { System.out.println(mainDatum.getFile()); } } + updateLibsMap(); if (initInterface != null) { initInterface.init(); initInterface = null; @@ -377,7 +397,26 @@ public class MusicContainer { } }); } - + public void updateLibsMap(){ + for (MusicData musicData : mainData) { + List artist; + List album; + if(artistMapList.containsKey(musicData.getArtist())){ + artist=artistMapList.get(musicData.getArtist()); + }else{ + artist=new ArrayList<>(); + } + if(albumMapList.containsKey(musicData.getAlbum())){ + album=albumMapList.get(musicData.getAlbum()); + }else{ + album=new ArrayList<>(); + } + artist.add(musicData); + album.add(musicData); + albumMapList.put(musicData.getAlbum(),album); + artistMapList.put(musicData.getArtist(),artist); + } + } public MusicData findMusic(String md5,List list) { for (MusicData data : list) { if (data.getMd5() == null) { diff --git a/app/src/main/java/com/yutou/nas_music_player/tools/AppTools.java b/app/src/main/java/com/yutou/nas_music_player/tools/AppTools.java index 0edb144..f9050bd 100644 --- a/app/src/main/java/com/yutou/nas_music_player/tools/AppTools.java +++ b/app/src/main/java/com/yutou/nas_music_player/tools/AppTools.java @@ -5,6 +5,11 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import com.kaopiz.kprogresshud.KProgressHUD; +import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.ImageLoader; +import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; +import com.yutou.nas_music_player.R; import java.io.File; import java.io.FileNotFoundException; @@ -51,7 +56,7 @@ public class AppTools { } public static Bitmap getSaveBitmap(String saveKey){ - String path=ConfigTools.getPreferences().getString(getMD5(saveKey),null); + String path=ConfigTools.getPreferences().getString("img_"+getMD5(saveKey),null); if(path==null){ return null; } @@ -82,5 +87,27 @@ public class AppTools { } return stringBuilder.toString(); } + private static DisplayImageOptions initDisplayOptions() { + DisplayImageOptions.Builder displayImageOptionsBuilder = new DisplayImageOptions.Builder(); + displayImageOptionsBuilder.cacheInMemory(false); + displayImageOptionsBuilder.cacheOnDisk(true); + displayImageOptionsBuilder.showImageForEmptyUri(R.drawable.ic_launcher_background); + displayImageOptionsBuilder.showImageOnFail(R.mipmap.ic_launcher); + return displayImageOptionsBuilder.build(); + } + public static ImageLoader initImageLoader(Context context) { + + ImageLoader imageLoader = ImageLoader.getInstance(); + ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(context); + File cachePath = new File(context.getFilesDir().getAbsolutePath() + "/cache/"); + if (!cachePath.exists()) { + cachePath.exists(); + } + builder.diskCache(new UnlimitedDiskCache(cachePath)); + builder.defaultDisplayImageOptions(initDisplayOptions()); + + imageLoader.init(builder.build()); + return imageLoader; + } } diff --git a/app/src/main/java/com/yutou/nas_music_player/tools/Helpers.kt b/app/src/main/java/com/yutou/nas_music_player/tools/Helpers.kt new file mode 100644 index 0000000..6f5e523 --- /dev/null +++ b/app/src/main/java/com/yutou/nas_music_player/tools/Helpers.kt @@ -0,0 +1,20 @@ +package com.yutou.nas_music_player.tools + +class Helpers { + companion object { + fun sectionsHelper(sections: MutableList, test: ArrayList): HashMap { + val mapOfSections = hashMapOf() + var lastFound = 0 + test.forEachIndexed { index, s -> + if (sections.any { it == s }) { + val value = sections.indexOfFirst { it == s } + mapOfSections[index] = value + lastFound = value + } else { + mapOfSections[index] = lastFound + } + } + return mapOfSections + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yutou/nas_music_player/views/Fragments/MusicLibsFragment.java b/app/src/main/java/com/yutou/nas_music_player/views/Fragments/MusicLibsFragment.java new file mode 100644 index 0000000..a67c2bb --- /dev/null +++ b/app/src/main/java/com/yutou/nas_music_player/views/Fragments/MusicLibsFragment.java @@ -0,0 +1,60 @@ +package com.yutou.nas_music_player.views.Fragments; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem; +import com.yutou.nas_music_player.Adapters.MusicLibsAdapter; +import com.yutou.nas_music_player.R; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; + +import java.util.HashMap; +import java.util.Map; + +import in.myinnos.alphabetsindexfastscrollrecycler.IndexFastScrollRecyclerView; + +public class MusicLibsFragment extends Fragment { + public static Map map = new HashMap<>(); + private Context context; + private View view; + private IndexFastScrollRecyclerView recyclerView; + private int model=1; + public MusicLibsFragment(){ + + } + public MusicLibsFragment(Context context,int model){ + this.context=context; + this.model=model; + } + public void setModel(int model){ + this.model=model; + adapter.initData(model); + adapter.notifyDataSetChanged(); + } + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + view=inflater.inflate(R.layout.fragment_music_libs,null); + int id = FragmentPagerItem.getPosition(getArguments()); + if (!map.containsKey(id)) { + map.put(id, this); + } + initViews(); + return view; + } + private MusicLibsAdapter adapter; + public void initViews(){ + + recyclerView=view.findViewById(R.id.fast_scroller_recycler); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + adapter=new MusicLibsAdapter(model); + recyclerView.setAdapter(adapter); + } +} diff --git a/app/src/main/java/com/yutou/nas_music_player/views/MainActivity.java b/app/src/main/java/com/yutou/nas_music_player/views/MainActivity.java index 18bf060..46a0f0f 100644 --- a/app/src/main/java/com/yutou/nas_music_player/views/MainActivity.java +++ b/app/src/main/java/com/yutou/nas_music_player/views/MainActivity.java @@ -5,7 +5,6 @@ import androidx.core.app.ActivityOptionsCompat; import androidx.core.util.Pair; import android.annotation.SuppressLint; -import android.app.ActivityOptions; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -34,7 +33,6 @@ import com.yutou.nas_music_player.tools.AppData; import com.yutou.nas_music_player.tools.AppTools; import com.yutou.nas_music_player.tools.ConfigTools; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Timer; @@ -188,11 +186,20 @@ public class MainActivity extends AppCompatActivity { Pair pNext = Pair.create((View) next, "next"); Pair pTitle = Pair.create((View) title, "title"); Pair pArtist = Pair.create((View) artist, "artist"); + Pair pBar = Pair.create((View) seekBar, "bar"); //ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this,list); - Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, pImage, pPrevious, pPlay, pNext, pTitle, pArtist).toBundle(); + Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, + pImage, + pPrevious, + pPlay, + pNext, + pBar, + pTitle, + pArtist).toBundle(); Intent intent = new Intent( MainActivity.this, PlayLibsActivity.class); + intent.putExtra("bar_pos",seekBar.getProgress()); if (bundle != null) { startActivity(intent, bundle); } else { @@ -297,9 +304,9 @@ public class MainActivity extends AppCompatActivity { } private void initView() { - play = findViewById(R.id.play); - next = findViewById(R.id.next); - previous = findViewById(R.id.previous); + play = findViewById(R.id.collection); + next = findViewById(R.id.top); + previous = findViewById(R.id.dislike); album_image = findViewById(R.id.album_image); background_image = findViewById(R.id.background_image); title = findViewById(R.id.title); @@ -317,6 +324,16 @@ public class MainActivity extends AppCompatActivity { getWindow().setNavigationBarColor(color); } + @Override + protected void onDestroy() { + super.onDestroy(); + if(browserHelper!=null){ + browserHelper.onStop(); + browserHelper=null; + } + finish(); + } + private class PlayListener extends MediaControllerCompat.Callback { @SuppressLint("SetTextI18n") @Override diff --git a/app/src/main/java/com/yutou/nas_music_player/views/PlayLibsActivity.java b/app/src/main/java/com/yutou/nas_music_player/views/PlayLibsActivity.java index 317d233..6edb3d5 100644 --- a/app/src/main/java/com/yutou/nas_music_player/views/PlayLibsActivity.java +++ b/app/src/main/java/com/yutou/nas_music_player/views/PlayLibsActivity.java @@ -2,74 +2,168 @@ package com.yutou.nas_music_player.views; import android.annotation.SuppressLint; import android.os.Bundle; +import android.os.Handler; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaControllerCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; +import android.view.View; import android.view.Window; import android.widget.ImageButton; import android.widget.ImageView; - -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; +import android.widget.ProgressBar; import com.bumptech.glide.Glide; import com.bumptech.glide.request.RequestOptions; +import com.ogaclejapan.smarttablayout.SmartTabLayout; +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter; +import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems; +import com.yutou.nas_music_player.Adapters.MusicLibsAdapter; import com.yutou.nas_music_player.Datas.MusicData; import com.yutou.nas_music_player.R; import com.yutou.nas_music_player.containers.MediaBrowserHelper; import com.yutou.nas_music_player.containers.MusicContainer; import com.yutou.nas_music_player.tools.AppData; -import com.yutou.nas_music_player.tools.ConfigTools; +import com.yutou.nas_music_player.views.Fragments.MusicLibsFragment; import java.util.List; -import java.util.Locale; import java.util.Timer; import java.util.TimerTask; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.viewpager.widget.ViewPager; import cc.ibooker.ztextviewlib.MarqueeTextView; -import jp.wasabeef.glide.transformations.BlurTransformation; import jp.wasabeef.glide.transformations.RoundedCornersTransformation; public class PlayLibsActivity extends AppCompatActivity { private ImageButton play, previous, next; + private ProgressBar progressBar; private MediaBrowserHelper browserHelper; private ImageView album_image; - private MarqueeTextView title, artist; - private PlayListener playListener; + private MarqueeTextView title, artist; + private Handler handler; + private int bar_pos=0; + + private SmartTabLayout tabLayout; + private ViewPager viewPager; + + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); super.onCreate(savedInstanceState); setContentView(R.layout.activity_play_list); initView(); + bar_pos=getIntent().getIntExtra("bar_pos",0); setPlayData(MusicContainer.getInstance().getNowPlayData()); browserHelper = new MediaBrowserHelper(this); - playListener=new PlayListener(); + PlayListener playListener = new PlayListener(); browserHelper.regPlayListener(playListener); + handler = new Handler(); + play.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + handler.post(new Runnable() { + @Override + public void run() { + if (browserHelper.isPlayer()) { + browserHelper.getTransportControls().pause(); + } else { + browserHelper.getTransportControls().play(); + } + + } + }); + + } + }); + next.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + handler.post(new Runnable() { + @Override + public void run() { + browserHelper.getTransportControls().skipToNext(); + } + }); + + } + }); + previous.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + handler.post(new Runnable() { + @Override + public void run() { + browserHelper.getTransportControls().skipToPrevious(); + + } + }); + } + }); } + private void initView() { - play = findViewById(R.id.play); - next = findViewById(R.id.next); - previous = findViewById(R.id.previous); + play = findViewById(R.id.collection); + next = findViewById(R.id.top); + previous = findViewById(R.id.dislike); album_image = findViewById(R.id.album_image); title = findViewById(R.id.title); artist = findViewById(R.id.artist); + progressBar = findViewById(R.id.progressBar); + tabLayout = findViewById(R.id.viewpagertab); + viewPager = findViewById(R.id.viewpager); + FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( + getSupportFragmentManager(), FragmentPagerItems.with(this) + .add("全部", MusicLibsFragment.class) + .add("专辑", MusicLibsFragment.class) + .create()); + viewPager.setAdapter(adapter); + tabLayout.setViewPager(viewPager); + tabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + MusicLibsFragment fragment = MusicLibsFragment.map.get(position); + if (fragment != null) { + switch (position){ + case 0: + fragment.setModel(MusicLibsAdapter.LIBS_MODEL_ALL); + break; + case 1: + fragment.setModel(MusicLibsAdapter.LIBS_MODEL_Album); + break; + } + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + }); } + private void setImage(MusicData data) { album_image.setImageBitmap(data.getImg()); Glide.with(this).load(data.getImg()) .apply(RequestOptions.bitmapTransform(new RoundedCornersTransformation(25, 3))) .into(album_image); } + @SuppressLint("SetTextI18n") private void setPlayData(final MusicData data) { - System.out.println("设置歌曲"); - System.out.println(data); if (data == null) return; title.setText(data.getTitle()); artist.setText(data.getArtist()); + progressBar.setMax((int) (data.getDurationAsDouble() * 1000)); + progressBar.setProgress(bar_pos); if (data.getImg() != null) { setImage(data); } else { @@ -94,16 +188,19 @@ public class PlayLibsActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); - browserHelper=null; + browserHelper.onStop(); + browserHelper = null; finish(); } + private class PlayListener extends MediaControllerCompat.Callback { @SuppressLint("SetTextI18n") @Override public void onPlaybackStateChanged(PlaybackStateCompat state) { super.onPlaybackStateChanged(state); if (state.getState() == PlaybackStateCompat.STATE_PLAYING) { + progressBar.setProgress((int) (state.getPosition())); play.setImageResource(android.R.drawable.ic_media_pause); } else { play.setImageResource(android.R.drawable.ic_media_play); diff --git a/app/src/main/res/drawable-v24/ic_dir.png b/app/src/main/res/drawable-v24/ic_dir.png new file mode 100644 index 0000000000000000000000000000000000000000..8e3ed3547c6f38c9b72ec71d16cc63a1a2cd5822 GIT binary patch literal 1316 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_hi_res.png b/app/src/main/res/drawable/ic_hi_res.png new file mode 100644 index 0000000000000000000000000000000000000000..54afd7f4c4eaf1157bb1027d5f07f8e7d31e63a6 GIT binary patch literal 22562 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 + android:textColor="@color/colorBlack" + android:transitionName="bar" /> @@ -148,7 +149,7 @@ app:srcCompat="@drawable/ic_play_random" /> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_music_libs_item.xml b/app/src/main/res/layout/layout_music_libs_item.xml new file mode 100644 index 0000000..fcbe6ed --- /dev/null +++ b/app/src/main/res/layout/layout_music_libs_item.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_play.xml b/app/src/main/res/layout/layout_play.xml index 4ceb1f3..9551ed3 100644 --- a/app/src/main/res/layout/layout_play.xml +++ b/app/src/main/res/layout/layout_play.xml @@ -3,89 +3,108 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal"> - - + android:orientation="vertical"> - - - - - - + - + - + - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8458c38..70312a2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = "1.4.10" + repositories { google() jcenter() @@ -7,6 +9,9 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/gradle.properties b/gradle.properties index c52ac9b..4d15d01 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,4 +16,6 @@ org.gradle.jvmargs=-Xmx2048m # https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official \ No newline at end of file