diff --git a/app/src/main/java/com/hi/music/player/adapter/AdapterSuggestion.java b/app/src/main/java/com/hi/music/player/adapter/AdapterSuggestion.java new file mode 100644 index 0000000..64db4cb --- /dev/null +++ b/app/src/main/java/com/hi/music/player/adapter/AdapterSuggestion.java @@ -0,0 +1,46 @@ +package com.hi.music.player.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.hi.music.player.databinding.ItemSuggestionBinding; + +public class AdapterSuggestion extends BaseAdapter { + + @Override + protected ItemSuggestionBinding getViewBinding(ViewGroup parent) { + return ItemSuggestionBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + VHolder itemHolder = (VHolder) holder; + ItemSuggestionBinding vb = itemHolder.getVb(); + String text = data.get(position); + vb.tvSuggestion.setText(text); + vb.relayout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(homeItemClickListener!= null){ + homeItemClickListener.onClickItemSuggestion(true,text); + } + + } + }); + + vb.imFillIn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(homeItemClickListener!= null){ + homeItemClickListener.onClickItemSuggestion(false,text); + } + } + }); + } + + +} diff --git a/app/src/main/java/com/hi/music/player/api/HomeItemClickListener.java b/app/src/main/java/com/hi/music/player/api/HomeItemClickListener.java index 2ff7fcb..19ca3e2 100644 --- a/app/src/main/java/com/hi/music/player/api/HomeItemClickListener.java +++ b/app/src/main/java/com/hi/music/player/api/HomeItemClickListener.java @@ -23,4 +23,15 @@ public interface HomeItemClickListener { default void onClickItemCategoryList(ResponsePlayListInfo data,int musicIndex) { } + + + /** + * 点击了搜索建议 + * @param isSearch true 直接搜索 false 输入搜索建议文字 + * @param data + */ + default void onClickItemSuggestion(boolean isSearch,String data) { + + } + } diff --git a/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearch.java b/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearch.java new file mode 100644 index 0000000..e9f6e8b --- /dev/null +++ b/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearch.java @@ -0,0 +1,34 @@ +package com.hi.music.player.javabean.requestbody; + +import com.hi.music.player.javabean.requestbody.child.Client; +import com.hi.music.player.javabean.requestbody.child.ContextBody; + +import java.io.Serializable; + + +/** + * 搜索建议接口 + */ +public class BodySearch implements Serializable { + + private String query = ""; + private ContextBody context = new ContextBody(); + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + + + public ContextBody getContext() { + return context; + } + + public void setContext(ContextBody context) { + this.context = context; + } +} diff --git a/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearchSuggestion.java b/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearchSuggestion.java new file mode 100644 index 0000000..f55b0f2 --- /dev/null +++ b/app/src/main/java/com/hi/music/player/javabean/requestbody/BodySearchSuggestion.java @@ -0,0 +1,34 @@ +package com.hi.music.player.javabean.requestbody; + +import com.hi.music.player.javabean.requestbody.child.Client; +import com.hi.music.player.javabean.requestbody.child.ContextBody; + +import java.io.Serializable; + + +/** + * 搜索建议接口 + */ +public class BodySearchSuggestion implements Serializable { + + private String input = ""; + + + public String getInput() { + return input; + } + + public void setInput(String input) { + this.input = input; + } + + private ContextBody context = new ContextBody(); + + public ContextBody getContext() { + return context; + } + + public void setContext(ContextBody context) { + this.context = context; + } +} diff --git a/app/src/main/java/com/hi/music/player/javabean/requestbody/child/Client.java b/app/src/main/java/com/hi/music/player/javabean/requestbody/child/Client.java new file mode 100644 index 0000000..4d66952 --- /dev/null +++ b/app/src/main/java/com/hi/music/player/javabean/requestbody/child/Client.java @@ -0,0 +1,38 @@ +package com.hi.music.player.javabean.requestbody.child; + +import java.io.Serializable; +import java.util.Locale; + + +public class Client implements Serializable { + private String clientName = "WEB_REMIX"; + //1.20240506.01.00 + private String clientVersion = "1.20220918"; + private String hl = Locale.getDefault().getLanguage(); + private String gl = "US"; + private String platform = "DESKTOP"; + + private String visitorData; + + public String getVisitorData() { + return visitorData; + } + + public void setVisitorData(String visitorData) { + this.visitorData = visitorData; + } + + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public void setClientVersion(String clientVersion) { + this.clientVersion = clientVersion; + } + + public void setPlatform(String platform) { + this.platform = platform; + } +} + diff --git a/app/src/main/java/com/hi/music/player/javabean/requestbody/child/ContextBody.java b/app/src/main/java/com/hi/music/player/javabean/requestbody/child/ContextBody.java index 0d2987a..e9d8a65 100644 --- a/app/src/main/java/com/hi/music/player/javabean/requestbody/child/ContextBody.java +++ b/app/src/main/java/com/hi/music/player/javabean/requestbody/child/ContextBody.java @@ -23,37 +23,7 @@ public class ContextBody { } - public static class Client implements Serializable { - private String clientName = "WEB_REMIX"; - //1.20240506.01.00 - private String clientVersion = "1.20220918"; - private String hl = Locale.getDefault().getLanguage(); - private String gl = "US"; - private String platform = "DESKTOP"; - private String visitorData; - - public String getVisitorData() { - return visitorData; - } - - public void setVisitorData(String visitorData) { - this.visitorData = visitorData; - } - - - public void setClientName(String clientName) { - this.clientName = clientName; - } - - public void setClientVersion(String clientVersion) { - this.clientVersion = clientVersion; - } - - public void setPlatform(String platform) { - this.platform = platform; - } - } public static class ThirdParty{ //https://www.youtube.com/watch?v=UqyT8IEBkvY diff --git a/app/src/main/java/com/hi/music/player/network/JsonHelper.java b/app/src/main/java/com/hi/music/player/network/JsonHelper.java index d21b6eb..761383f 100644 --- a/app/src/main/java/com/hi/music/player/network/JsonHelper.java +++ b/app/src/main/java/com/hi/music/player/network/JsonHelper.java @@ -323,6 +323,84 @@ public class JsonHelper { } + public static List ResolveSearchSuggestion(JSONObject jsonObject) { + try { + List stringList = new ArrayList<>(); + JSONArray contents = jsonObject.getJSONArray("contents"); + for (int i = 0; i < contents.length(); i++) { + JSONArray jsonArray = contents.getJSONObject(i) + .getJSONObject("searchSuggestionsSectionRenderer") + .getJSONArray("contents"); + + for (int j = 0; j < jsonArray.length(); j++) { + + JSONObject searchSuggestionRenderer = jsonArray.getJSONObject(j) + .optJSONObject("searchSuggestionRenderer"); + if (searchSuggestionRenderer != null) { + String string = searchSuggestionRenderer + .getJSONObject("navigationEndpoint") + .getJSONObject("searchEndpoint") + .getString("query"); + stringList.add(string); + } + + } + + } + + return stringList; + + } catch (JSONException e) { + CommonUtils.LogErrorMsg("--" + e.getMessage()); + return null; + } + + } + + + /** + * 解析搜索结果 + * + * @param jsonObject + */ + public static void ResolveSearchResult(JSONObject jsonObject) { + try { + JSONArray jsonArray = jsonObject.getJSONObject("contents") + .getJSONObject("tabbedSearchResultsRenderer") + .getJSONArray("tabs") + .getJSONObject(0) + .getJSONObject("tabRenderer") + .getJSONObject("content") + .getJSONObject("sectionListRenderer") + .getJSONArray("contents"); + for(int i =0;i2){ + } else if (length > 2) { index = length - 2; } String pngUrl = jsonArray.getJSONObject(index).getString("url"); - CommonUtils.LogMsg("----------取封面index="+index); + CommonUtils.LogMsg("----------取封面index=" + index); return pngUrl; } catch (JSONException exception) { diff --git a/app/src/main/java/com/hi/music/player/network/MusicApi.java b/app/src/main/java/com/hi/music/player/network/MusicApi.java index 7be6819..3c99056 100644 --- a/app/src/main/java/com/hi/music/player/network/MusicApi.java +++ b/app/src/main/java/com/hi/music/player/network/MusicApi.java @@ -51,7 +51,24 @@ public interface MusicApi { //首页分类项下的播放列表子页面 (类型1:单曲合集、2:专辑、3:音乐视频合集 ,不同类型返回数据结构有区别) @POST("youtubei/v1/browse?prettyPrint=false") - @Headers("X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8") + @Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"}) Observable getCategoryList(@Body RequestBody requestBody); + + + + + @POST("youtubei/v1/music/get_search_suggestions?prettyPrint=false") + @Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", + "X-Goog-FieldMask:contents.searchSuggestionsSectionRenderer.contents.searchSuggestionRenderer.navigationEndpoint.searchEndpoint.query"}) + Observable getSearchSuggestion(@Body RequestBody requestBody); + + + + +// "X-Goog-FieldMask:contents.tabbedSearchResultsRenderer.tabs.tabRenderer.content.sectionListRenderer.contents.musicShelfRenderer(continuations,contents.musicResponsiveListItemRenderer(flexColumns,fixedColumns,thumbnail,navigationEndpoint))" + @POST("youtubei/v1/search?prettyPrint=false") + @Headers({"X-Goog-Api-Key:AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8"}) + Observable getSearch(@Body RequestBody requestBody); + } diff --git a/app/src/main/java/com/hi/music/player/network/RetrofitManager.java b/app/src/main/java/com/hi/music/player/network/RetrofitManager.java index c051aa3..76948a8 100644 --- a/app/src/main/java/com/hi/music/player/network/RetrofitManager.java +++ b/app/src/main/java/com/hi/music/player/network/RetrofitManager.java @@ -5,6 +5,9 @@ import com.hi.music.player.api.RequestListener; import com.hi.music.player.javabean.requestbody.BodyHome; import com.hi.music.player.javabean.requestbody.BodyPlay; import com.hi.music.player.javabean.requestbody.BodyPlayUrl; +import com.hi.music.player.javabean.requestbody.BodySearch; +import com.hi.music.player.javabean.requestbody.BodySearchSuggestion; +import com.hi.music.player.javabean.requestbody.child.Client; import com.hi.music.player.javabean.requestbody.child.ContextBody; import java.util.HashMap; @@ -32,8 +35,8 @@ public class RetrofitManager { public MediaType JSON = MediaType.get("application/json; charset=utf-8"); private MusicApi musicApi; - private String header1="playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)"; - private String header ="contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer,"+header1+"))"; + private String header1 = "playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)"; + private String header = "contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs.tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer(continuations,contents(automixPreviewVideoRenderer," + header1 + "))"; private RetrofitManager() { @@ -89,7 +92,7 @@ public class RetrofitManager { .subscribe(new ObserverWrapper(requestListener)); } - public void getHomeMoreData(String continuation,String itct,String visitorData,RequestListener requestListener) { + public void getHomeMoreData(String continuation, String itct, String visitorData, RequestListener requestListener) { BodyHome bodyHome = new BodyHome(); bodyHome.getContext().getClient().setVisitorData(visitorData); Gson gson = new Gson(); @@ -97,12 +100,12 @@ public class RetrofitManager { RequestBody requestBody = RequestBody.Companion.create(s, JSON); HashMap stringHashMap = new HashMap<>(); - stringHashMap.put("ctoken",continuation); - stringHashMap.put("continuation",continuation); - stringHashMap.put("type","next"); - stringHashMap.put("itct",itct); - stringHashMap.put("prettyPrint","false"); - musicApi.getHomeMoreData(continuation,continuation,"next",itct,false,requestBody) + stringHashMap.put("ctoken", continuation); + stringHashMap.put("continuation", continuation); + stringHashMap.put("type", "next"); + stringHashMap.put("itct", itct); + stringHashMap.put("prettyPrint", "false"); + musicApi.getHomeMoreData(continuation, continuation, "next", itct, false, requestBody) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -119,7 +122,7 @@ public class RetrofitManager { Gson gson = new Gson(); String s = gson.toJson(bodyPlay); RequestBody requestBody = RequestBody.Companion.create(s, JSON); - musicApi.getMusicPlayPage(header,requestBody) + musicApi.getMusicPlayPage(header, requestBody) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -127,15 +130,14 @@ public class RetrofitManager { } - - public void getPlayUrl(String videoId,RequestListener requestListener) { + public void getPlayUrl(String videoId, RequestListener requestListener) { BodyPlayUrl bodyPlay = new BodyPlayUrl(); bodyPlay.setVideoId(videoId); - ContextBody.Client client = bodyPlay.getContext().getClient(); + Client client = bodyPlay.getContext().getClient(); client.setClientName("ANDROID_MUSIC"); client.setClientVersion("5.28.1"); client.setPlatform("MOBILE"); - bodyPlay.getContext().getThirdParty().setEmbedUrl("https://www.youtube.com/watch?v="+videoId); + bodyPlay.getContext().getThirdParty().setEmbedUrl("https://www.youtube.com/watch?v=" + videoId); Gson gson = new Gson(); @@ -149,13 +151,12 @@ public class RetrofitManager { } - - public void getCategoryList(String browserId,RequestListener requestListener) { + public void getCategoryList(String browserId, RequestListener requestListener) { BodyHome bodyHome = new BodyHome(); bodyHome.setBrowseId(browserId); // bodyHome.setBrowseId("VLPLI-asvmHZWNo_xjMMfD_v2O2lTyCdrjaK"); - ContextBody.Client client = bodyHome.getContext().getClient(); + Client client = bodyHome.getContext().getClient(); client.setClientVersion("1.20240506.01.00"); @@ -164,13 +165,44 @@ public class RetrofitManager { RequestBody requestBody = RequestBody.Companion.create(s, JSON); - musicApi.getCategoryList(requestBody) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new ObserverWrapper(requestListener)); + .subscribe(new ObserverWrapper<>(requestListener)); } + + + public void getSearchSuggestion(String input, RequestListener requestListener) { + BodySearchSuggestion body = new BodySearchSuggestion(); + body.setInput(input); + Client client = body.getContext().getClient(); + client.setClientVersion("1.20240506.01.00"); + Gson gson = new Gson(); + String s = gson.toJson(body); + RequestBody requestBody = RequestBody.Companion.create(s, JSON); + musicApi.getSearchSuggestion(requestBody) + .subscribeOn(Schedulers.io()) + .unsubscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new ObserverWrapper<>(requestListener)); + } + + + public void getSearch(String query, RequestListener requestListener) { + BodySearch body = new BodySearch(); + body.setQuery(query); + Client client = body.getContext().getClient(); + client.setClientVersion("1.20240506.01.00"); + Gson gson = new Gson(); + String s = gson.toJson(body); + RequestBody requestBody = RequestBody.Companion.create(s, JSON); + musicApi.getSearch(requestBody) + .subscribeOn(Schedulers.io()) + .unsubscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new ObserverWrapper<>(requestListener)); + } } diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/SearchFragment.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/SearchFragment.java index eabcf1f..98ca447 100644 --- a/app/src/main/java/com/hi/music/player/ui/fragmnt/SearchFragment.java +++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/SearchFragment.java @@ -1,11 +1,29 @@ package com.hi.music.player.ui.fragmnt; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.TextView; + +import androidx.lifecycle.Observer; +import androidx.recyclerview.widget.LinearLayoutManager; + +import com.hi.music.player.adapter.AdapterSuggestion; +import com.hi.music.player.api.HomeItemClickListener; import com.hi.music.player.databinding.FragmentSearchBinding; +import com.hi.music.player.helper.CommonUtils; +import com.hi.music.player.ui.fragmnt.viewmodel.VMSearch; + +import java.util.List; -public class SearchFragment extends BaseFragment { +public class SearchFragment extends BaseFragment implements HomeItemClickListener, View.OnClickListener { + private VMSearch vmSearch; + @Override protected FragmentSearchBinding getFragmentVb() { return FragmentSearchBinding.inflate(getLayoutInflater()); @@ -13,6 +31,82 @@ public class SearchFragment extends BaseFragment { @Override protected void initView() { +// Vb.etSearch.requestFocus(); + vmSearch = getFragmentScopeViewModel(VMSearch.class); + Vb.etSearch.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + String input = s.toString(); + if (!input.isEmpty()) { + vmSearch.getSuggestion(input); + } + + } + }); + Vb.etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH) { + String s = v.getText().toString(); + CommonUtils.LogMsg("------------v=" + s); + startQuery(s); + return true; + } else + return false; + } + }); + initSuggestionRecycler(); + } + + private void initSuggestionRecycler() { + AdapterSuggestion adapterSuggestion = new AdapterSuggestion(); + Vb.recyclerSuggestion.setLayoutManager(new LinearLayoutManager(requireContext())); + Vb.recyclerSuggestion.setAdapter(adapterSuggestion); + adapterSuggestion.setHomeItemClickListener(this); + Vb.imCancel.setOnClickListener(this); + vmSearch.suggestion.observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(List strings) { + if (strings != null) { + adapterSuggestion.setData(strings); + CommonUtils.LogMsg("------------更新="); + } + + } + }); + } + + private void startQuery(String query){ + Vb.recyclerSuggestion.setVisibility(View.GONE); + Vb.recyclerResult.setVisibility(View.VISIBLE); + vmSearch.getSearchResult(query); + } + + @Override + public void onClickItemSuggestion(boolean isSearch, String data) { + if (isSearch) { + startQuery(data); + } else { + Vb.etSearch.setText(data); + } + } + + + @Override + public void onClick(View v) { + if (v.equals(Vb.imCancel)) { + Vb.etSearch.setText(""); + } } } \ No newline at end of file diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/VMSearch.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/VMSearch.java new file mode 100644 index 0000000..968c00e --- /dev/null +++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/VMSearch.java @@ -0,0 +1,66 @@ +package com.hi.music.player.ui.fragmnt.viewmodel; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +import com.hi.music.player.api.RequestListener; +import com.hi.music.player.helper.CommonUtils; +import com.hi.music.player.javabean.response.ResponseHome; +import com.hi.music.player.network.JsonHelper; +import com.hi.music.player.network.RetrofitManager; + +import org.json.JSONObject; + +import java.util.List; + +import okhttp3.ResponseBody; + +public class VMSearch extends ViewModel { + private MutableLiveData> _suggestion = new MutableLiveData>(); + public LiveData> suggestion = _suggestion; + public void getSuggestion(String input) { + RetrofitManager.getInstance().getSearchSuggestion(input,new RequestListener() { + + @Override + public void onFail(String errorMsg) { + _suggestion.setValue(null); + } + + @Override + public void onSuccess(JSONObject data) { + if (data != null) { + List stringList = JsonHelper.ResolveSearchSuggestion(data); + CommonUtils.LogMsg("------------onSuccess= stringList="+stringList ); + _suggestion.setValue(stringList); + } else { + _suggestion.setValue(null); + } + + } + }); + } + + + public void getSearchResult(String query) { + RetrofitManager.getInstance().getSearch(query, new RequestListener() { + + @Override + public void onFail(String errorMsg) { +// _data.setValue(null); + } + + @Override + public void onSuccess(JSONObject data) { + if (data != null) { + JsonHelper.ResolveSearchResult(data); +// _data.setValue(responseHome); + } else { +// _data.setValue(null); + } + + } + }); + } + +} diff --git a/app/src/main/res/drawable/bg_search.xml b/app/src/main/res/drawable/bg_search.xml new file mode 100644 index 0000000..ecda9f0 --- /dev/null +++ b/app/src/main/res/drawable/bg_search.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/icon_cancel.xml b/app/src/main/res/drawable/icon_cancel.xml new file mode 100644 index 0000000..3a839bc --- /dev/null +++ b/app/src/main/res/drawable/icon_cancel.xml @@ -0,0 +1,20 @@ + + + + diff --git a/app/src/main/res/drawable/icon_fill_in.xml b/app/src/main/res/drawable/icon_fill_in.xml new file mode 100644 index 0000000..154ee4f --- /dev/null +++ b/app/src/main/res/drawable/icon_fill_in.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/icon_search.xml b/app/src/main/res/drawable/icon_search.xml new file mode 100644 index 0000000..cde8483 --- /dev/null +++ b/app/src/main/res/drawable/icon_search.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index d8bf0d1..b7dffcf 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -1,14 +1,63 @@ - - - + android:layout_height="50dp" + android:layout_marginStart="22dp" + android:layout_marginEnd="22dp" + android:layout_marginTop="16dp" + android:id="@+id/layout_et" + android:background="@drawable/bg_search" > - \ No newline at end of file + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_suggestion.xml b/app/src/main/res/layout/item_suggestion.xml new file mode 100644 index 0000000..6e4ae7f --- /dev/null +++ b/app/src/main/res/layout/item_suggestion.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4f92588..c9c6ad8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,4 +24,5 @@ Play next Try again An error occurred + Search songs, artists… \ No newline at end of file