完成了歌手照片保存到本地的功能,并在主活动播放栏显示歌手照片

pull/1/head
jsyjst 7 years ago
parent 34b212b353
commit ee18260c22

@ -5,6 +5,7 @@ package com.example.musicplayer.constant;
*/
public class PlayerStatus {
public static final String PLAYER_STATUS="PlayerStatus";
public static final int PLAY=1;
public static final int PAUSE=2;
public static final int STOP=3;

@ -12,6 +12,7 @@ public class Mp3Info {
private String url;
private long albumId;
private long id;
private boolean isImgSave;//照片是否保存到本地
public void setId(long id) {
this.id = id;
@ -68,4 +69,12 @@ public class Mp3Info {
public long getAlbumId() {
return albumId;
}
public void setImgSave(boolean imgSave) {
isImgSave = imgSave;
}
public boolean isImgSave() {
return isImgSave;
}
}

@ -91,6 +91,8 @@ public class Song implements Serializable {
this.albumId = albumId;
}
public String toString(){
return "artist="+artist+",title="+title+",url="+url+",duration="+duration+
",size"+size+",currentTime="+currentTime+",current="+current+",albumId="+albumId;

@ -111,6 +111,7 @@ public class PlayerService extends Service {
isPlaying=false;
mediaPlayer.pause();
isPause = true;
sendBroadcast(new Intent("SONG_PAUSE"));//发送暂停的广播给主活动
}
}
@ -141,6 +142,29 @@ public class PlayerService extends Service {
mPlayStatusBinder.play(0);
sendBroadcast(new Intent("android.song.change")); //发送广播改变播放栏的信息
sendBroadcast(new Intent("android.song.change.local.song.list"));//发送广播改变当地列表的显示
}
public void last(){
mCurrent=FileHelper.getSong().getCurrent();
mCurrent--;
if(mCurrent==-1){
mCurrent=mMp3InfoList.size()-1;
}
//将歌曲的信息保存起来
Song song=FileHelper.getSong();
song.setCurrent(mCurrent);
song.setTitle(mMp3InfoList.get(mCurrent).getTitle());
song.setArtist(mMp3InfoList.get(mCurrent).getArtist());
song.setDuration(mMp3InfoList.get(mCurrent).getDuration());
song.setUrl(mMp3InfoList.get(mCurrent).getUrl());
song.setId(mMp3InfoList.get(mCurrent).getId());
song.setAlbumId(mMp3InfoList.get(mCurrent).getAlbumId());
FileHelper.saveSong(song);
mPlayStatusBinder.play(0);
sendBroadcast(new Intent("android.song.change")); //发送广播改变播放栏的信息
sendBroadcast(new Intent("android.song.change.local.song.list"));//发送广播改变当地列表的显示
}
@ -159,6 +183,7 @@ public class PlayerService extends Service {
}
}
}

@ -1,9 +1,21 @@
package com.example.musicplayer.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.example.musicplayer.R;
import com.example.musicplayer.contract.IPlayContract;
import com.example.musicplayer.entiy.Song;
import java.io.File;
@ -14,30 +26,33 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import de.hdodenhof.circleimageview.CircleImageView;
/**
* user
* user
* Created by on 2018/7/24.
*/
public class FileHelper {
private static String TAG = "FileHelper";
/**
* person
* params:
* p:person
*/
* person
* params:
* p:person
*/
public static void saveSong(Song song){
public static void saveSong(Song song) {
try {
File file=new File(Environment.getExternalStorageDirectory()+"/yuanmusic/");
if(!file.exists()){
Log.d("Login","------------------"+Environment.getExternalStorageDirectory());
File file = new File(Environment.getExternalStorageDirectory() + "/yuanmusic/");
if (!file.exists()) {
Log.d("Login", "------------------" + Environment.getExternalStorageDirectory());
file.mkdirs();
}
//写对象流的对象
File userFile=new File(file,"song.txt");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(userFile));
File userFile = new File(file, "song.txt");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(userFile));
oos.writeObject(song); //将Person对象p写入到oos中
oos.close(); //关闭文件流
} catch (FileNotFoundException e) {
@ -48,19 +63,20 @@ public class FileHelper {
e.printStackTrace();
}
}
/**
* Person
*/
public static Song getSong(){
/**
* Person
*/
public static Song getSong() {
try {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory()+"/yuanmusic/song.txt"));
Song song=(Song)ois.readObject();//读出对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Environment.getExternalStorageDirectory() + "/yuanmusic/song.txt"));
Song song = (Song) ois.readObject();//读出对象
return song; //返回对象
} catch (FileNotFoundException e) {
e.printStackTrace();
Song song=new Song();
return song;
Song song = new Song();
return song;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -71,4 +87,45 @@ public class FileHelper {
return null;
}
}
//保存图片到本地
public static void saveImgToNative(Context context, Bitmap bitmap, String singer) {
File file = new File(Environment.getExternalStorageDirectory() + "/yuanmusic/img/");
if (!file.exists()) {
file.mkdirs();
}
File singerImgFile = new File(file, singer + ".jpg");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(singerImgFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.d(TAG, "saveImgToNative: fileNotFound");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void setSingerImg (Context context, String singer, ImageView view) {
if(singer.contains("/")){
String[] s=singer.split("/");
singer=s[0];
}
singer=singer.trim();
String imgUrl = Environment.getExternalStorageDirectory() + "/yuanmusic/img/" + singer + ".jpg";
Glide.with(context)
.load(imgUrl)
.apply(RequestOptions.errorOf(R.drawable.background))
.into(view);
}
}

@ -147,6 +147,14 @@ public class MediaUtil {
}
return min + ":" + sec.trim().substring(0, 2);
}
public static String formatSinger(String singer){
if(singer.contains("/")){
String []s=singer.split("/");
singer=s[0];
}
return singer.trim();
}
}

@ -26,6 +26,7 @@ import android.widget.SeekBar;
import android.widget.TextView;
import com.example.musicplayer.R;
import com.example.musicplayer.constant.PlayerStatus;
import com.example.musicplayer.entiy.Song;
import com.example.musicplayer.service.PlayerService;
import com.example.musicplayer.util.FileHelper;
@ -36,6 +37,7 @@ import de.hdodenhof.circleimageview.CircleImageView;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private boolean isChange; //拖动进度条
private boolean isSeek;//标记是否在暂停的时候拖动进度条
private boolean flag; //用做暂停的标记
@ -74,6 +76,7 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.song.change");
intentFilter.addAction("SONG_PAUSE");
songChangeReceiver = new SongChangeReceiver();
registerReceiver(songChangeReceiver, intentFilter);
initView();
@ -87,16 +90,15 @@ public class MainActivity extends AppCompatActivity {
mLinear = findViewById(R.id.linear_player);
mSeekBar = findViewById(R.id.sb_progress);
mNextIv = findViewById(R.id.song_next);
mCoverIv=findViewById(R.id.circle_img);
mCoverIv = findViewById(R.id.circle_img);
//设置属性动画
mCircleAnimator=ObjectAnimator.ofFloat(mCoverIv,"rotation",0.0f,360.0f);
mCircleAnimator = ObjectAnimator.ofFloat(mCoverIv, "rotation", 0.0f, 360.0f);
mCircleAnimator.setDuration(30000);
mCircleAnimator.setInterpolator(new LinearInterpolator());
mCircleAnimator.setRepeatCount(-1);
mCircleAnimator.setRepeatMode(ValueAnimator.RESTART);
if (mSong.getTitle() != null) {
//启动服务
Intent playIntent = new Intent(MainActivity.this, PlayerService.class);
@ -108,6 +110,7 @@ public class MainActivity extends AppCompatActivity {
mSingerTv.setText(mSong.getArtist());
mSeekBar.setMax((int) mSong.getDuration());
mSeekBar.setProgress((int) mSong.getCurrentTime());
FileHelper.setSingerImg(MainActivity.this,mSong.getArtist(),mCoverIv);
} else {
mLinear.setVisibility(View.GONE);
@ -194,7 +197,14 @@ public class MainActivity extends AppCompatActivity {
mLinear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent toPlayActivityIntent=new Intent(MainActivity.this,PlayActivity.class);
Intent toPlayActivityIntent = new Intent(MainActivity.this, PlayActivity.class);
if (mPlayStatusBinder.isPlaying()) {
Song song=FileHelper.getSong();
song.setCurrentTime(mPlayStatusBinder.getCurrentTime());
FileHelper.saveSong(song);
toPlayActivityIntent.putExtra(PlayerStatus.PLAYER_STATUS, PlayerStatus.PLAY);
}
startActivity(toPlayActivityIntent,
ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle());
}
@ -241,15 +251,23 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
mSong = FileHelper.getSong();
mSongNameTv.setText(mSong.getTitle());
mSingerTv.setText(mSong.getArtist());
mPlayerBtn.setSelected(true);
mCoverIv.setImageBitmap(MediaUtil.getMusicBitmap(MainActivity.this,mSong.getId(),mSong.getAlbumId()));
mCircleAnimator.start();
FileHelper.setSingerImg(MainActivity.this,mSong.getArtist(),mCoverIv);
mSeekBar.setMax((int) mSong.getDuration());
mSeekBarThread = new Thread(new SeekBarThread());
mSeekBarThread.start();
if(action.equals("SONG_PAUSE")){
mPlayerBtn.setSelected(false);
mCircleAnimator.pause();
}else{
mPlayerBtn.setSelected(true);
mCircleAnimator.start();
mSeekBarThread = new Thread(new SeekBarThread());
mSeekBarThread.start();
}
}
}
}

@ -8,11 +8,13 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@ -27,13 +29,18 @@ import android.widget.SeekBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.example.musicplayer.R;
import com.example.musicplayer.base.BaseActivity;
import com.example.musicplayer.constant.PlayerStatus;
import com.example.musicplayer.contract.IPlayContract;
import com.example.musicplayer.entiy.Mp3Info;
import com.example.musicplayer.entiy.Song;
import com.example.musicplayer.presenter.PlayPresenter;
import com.example.musicplayer.service.PlayerService;
@ -45,10 +52,14 @@ import com.example.musicplayer.util.MediaUtil;
import com.example.musicplayer.widget.BackgroundAnimationRelativeLayout;
import com.example.musicplayer.widget.DiscView;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class PlayActivity extends BaseActivity implements IPlayContract.View, DiscView.IPlayInfo {
public class PlayActivity extends BaseActivity implements IPlayContract.View {
private String TAG = "PlayActivity";
@ -73,12 +84,12 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
private TextView mDurationTimeTv;
private DiscView mDisc; //唱碟
private ImageView mDiscImg; //唱碟中的歌手头像
private Bitmap mImgBmp;
private Button mGetImgAndLrcBtn;//获取封面和歌词
private BackgroundAnimationRelativeLayout mRootLayout;
private List<Mp3Info> mMp3InfoList;//用来判断是否有本地照片
//服务
private Thread mSeekBarThread;
@ -97,7 +108,7 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
}
};
private Handler mMusicHandler = new Handler(){
private Handler mMusicHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
@ -128,7 +139,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
registerReceiver(songChangeReceiver, mIntentFilter);
mRootLayout = findViewById(R.id.relative_root);
mSongTv = findViewById(R.id.tv_song);
mSingerTv = findViewById(R.id.tv_singer);
@ -137,13 +147,12 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
mNextBtn = findViewById(R.id.next);
mGetImgAndLrcBtn = findViewById(R.id.btn_get_img_lrc);
mSeekBar=findViewById(R.id.seek);
mDurationTimeTv=findViewById(R.id.tv_duration_time);
mCurrentTimeTv=findViewById(R.id.tv_current_time);
mSeekBar = findViewById(R.id.seek);
mDurationTimeTv = findViewById(R.id.tv_duration_time);
mCurrentTimeTv = findViewById(R.id.tv_current_time);
mDisc = findViewById(R.id.disc_view);
mDisc.setPlayInfoListener(this);
mDiscImg = findViewById(R.id.iv_disc_background);
@ -151,13 +160,22 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
Intent playIntent = new Intent(PlayActivity.this, PlayerService.class);
bindService(playIntent, connection, Context.BIND_AUTO_CREATE);
mSong=FileHelper.getSong();
mSong = FileHelper.getSong();
mMp3InfoList = MediaUtil.getMp3Info();
mSingerTv.setText(mSong.getArtist());
mSongTv.setText(mSong.getTitle());
mCurrentTimeTv.setText(MediaUtil.formatTime(0));
mCurrentTimeTv.setText(MediaUtil.formatTime(mSong.getCurrentTime()));
mDurationTimeTv.setText(MediaUtil.formatTime(mSong.getDuration()));
mSeekBar.setMax((int)mSong.getDuration());
mSeekBar.setMax((int) mSong.getDuration());
mSeekBar.setProgress((int) mSong.getCurrentTime());
setLocalImg(mSong.getArtist());
if (getIntent().getIntExtra(PlayerStatus.PLAYER_STATUS, 2) == 1) {
mDisc.play();
mPlayBtn.setSelected(true);
startUpdateSeekBarProgress();
}
}
@ -284,6 +302,15 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
} else {
mPlayBtn.setSelected(false);
}
mDisc.next();
}
});
mLastBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPlayStatusBinder.last();
mPlayBtn.setSelected(true);
mDisc.last();
}
});
}
@ -291,10 +318,10 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
@Override
public String getSingerName() {
Song song = FileHelper.getSong();
if(song.getArtist().contains("/")){
String[] s=song.getArtist().split("/");
if (song.getArtist().contains("/")) {
String[] s = song.getArtist().split("/");
return s[0].trim();
}else{
} else {
return song.getArtist().trim();
}
@ -313,11 +340,14 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
@Override
public void onResourceReady(@Nullable Drawable resource, Transition<? super Drawable> transition) {
Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
mImgBmp = bitmap;
mImgBmp = ((BitmapDrawable) resource).getBitmap();
//保存图片到本地
FileHelper.saveImgToNative(PlayActivity.this, mImgBmp, getSingerName());
Song song = FileHelper.getSong();
mMp3InfoList.get(song.getCurrent()).setImgSave(true);
try2UpdateMusicPicBackground(mImgBmp);
setDiscImg(mImgBmp);
CommonUtil.showToast(PlayActivity.this,"获取封面歌词成功");
CommonUtil.showToast(PlayActivity.this, "获取封面歌词成功");
mGetImgAndLrcBtn.setVisibility(View.GONE);
}
};
@ -335,32 +365,6 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
}
@Override
public void onMusicChanged(DiscView.MusicChangedStatus musicChangedStatus) {
switch (musicChangedStatus) {
case PLAY: {
//play();
break;
}
case PAUSE: {
// pause();
break;
}
case NEXT: {
// next();
break;
}
case LAST: {
// last();
break;
}
case STOP: {
// stop();
break;
}
}
}
//设置唱碟中歌手头像
private void setDiscImg(Bitmap bitmap) {
mDiscImg.setImageDrawable(mDisc.getDiscDrawable(bitmap));
@ -380,32 +384,65 @@ public class PlayActivity extends BaseActivity implements IPlayContract.View, Di
Song mSong = FileHelper.getSong();
mSongTv.setText(mSong.getTitle());
mSingerTv.setText(mSong.getArtist());
mDurationTimeTv.setText(MediaUtil.formatTime(mSong.getDuration()));
mPlayBtn.setSelected(true);
setLocalImg(mSong.getArtist());//显示照片
mSeekBar.setMax((int) mSong.getDuration());
startUpdateSeekBarProgress();
}
}
private class SeekBarThread implements Runnable {
@Override
public void run() {
while (!isChange && mPlayStatusBinder.isPlaying()) {
mSeekBar.setProgress((int) mPlayStatusBinder.getCurrentTime());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void startUpdateSeekBarProgress() {
/*避免重复发送Message*/
stopUpdateSeekBarProgress();
mMusicHandler.sendEmptyMessageDelayed(0,1000);
mMusicHandler.sendEmptyMessageDelayed(0, 1000);
}
private void stopUpdateSeekBarProgress() {
mMusicHandler.removeMessages(0);
}
private void setLocalImg(String singer) {
String imgUrl = Environment.getExternalStorageDirectory() + "/yuanmusic/img/"
+ MediaUtil.formatSinger(singer) + ".jpg";
SimpleTarget target = new SimpleTarget<Drawable>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
@Override
public void onResourceReady(@Nullable Drawable resource, Transition<? super Drawable> transition) {
mGetImgAndLrcBtn.setVisibility(View.GONE);
mImgBmp = ((BitmapDrawable) resource).getBitmap();
try2UpdateMusicPicBackground(mImgBmp);
setDiscImg(mImgBmp);
}
};
Glide.with(this)
.load(imgUrl)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
mGetImgAndLrcBtn.setVisibility(View.VISIBLE);
mGetImgAndLrcBtn.setText("获取封面和歌词");
setDiscImg(BitmapFactory.decodeResource(getResources(),R.drawable.default_disc));
return true;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.apply(RequestOptions.errorOf(R.drawable.background))
.into(target);
}
@Override
public void onDestroy() {
super.onDestroy();
unbindService(connection);
unregisterReceiver(songChangeReceiver);
}
}

@ -17,7 +17,6 @@ import android.view.animation.AccelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.example.musicplayer.R;
import com.example.musicplayer.util.CommonUtil;
@ -44,7 +43,6 @@ public class DiscView extends RelativeLayout {
public static final int DURATION_NEEDLE_ANIAMTOR = 500;
private NeedleAnimatorStatus needleAnimatorStatus = NeedleAnimatorStatus.IN_FAR_END;
private IPlayInfo mIPlayInfo;
private int mScreenWidth, mScreenHeight;
@ -66,15 +64,7 @@ public class DiscView extends RelativeLayout {
PLAY, PAUSE, STOP
}
/*DiscView需要触发的音乐切换状态播放、暂停、上/下一首、停止*/
public enum MusicChangedStatus {
PLAY, PAUSE, NEXT, LAST, STOP
}
public interface IPlayInfo {
/*用于更新音乐播放状态*/
void onMusicChanged(MusicChangedStatus musicChangedStatus);
}
public DiscView(Context context) {
this(context, null);
@ -207,9 +197,6 @@ public class DiscView extends RelativeLayout {
});
}
public void setPlayInfoListener(IPlayInfo listener) {
this.mIPlayInfo = listener;
}
@ -249,7 +236,7 @@ public class DiscView extends RelativeLayout {
public ObjectAnimator getDiscObjectAnimator(ImageView disc) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(disc, View.ROTATION, 0, 360);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.setDuration(20 * 1000);
objectAnimator.setDuration(30 * 1000);
objectAnimator.setInterpolator(new LinearInterpolator());
return objectAnimator;
@ -286,14 +273,7 @@ public class DiscView extends RelativeLayout {
* */
needleAnimatorStatus = NeedleAnimatorStatus.TO_FAR_END;
}
/**
* /
* */
if (musicStatus == MusicStatus.STOP) {
notifyMusicStatusChanged(MusicChangedStatus.STOP);
}else if (musicStatus == MusicStatus.PAUSE) {
notifyMusicStatusChanged(MusicChangedStatus.PAUSE);
}
}
/*播放唱盘动画*/
@ -303,12 +283,7 @@ public class DiscView extends RelativeLayout {
} else {
mObjectAnimator.start();
}
/**
*
* */
if (musicStatus != MusicStatus.PLAY) {
notifyMusicStatusChanged(MusicChangedStatus.PLAY);
}
}
/*暂停唱盘动画*/
@ -319,12 +294,6 @@ public class DiscView extends RelativeLayout {
}
public void notifyMusicStatusChanged(MusicChangedStatus musicChangedStatus) {
if (mIPlayInfo != null) {
mIPlayInfo.onMusicChanged(musicChangedStatus);
}
}
public void play() {
playAnimator();
}
@ -339,19 +308,15 @@ public class DiscView extends RelativeLayout {
pauseAnimator();
}
public void playOrPause() {
if (musicStatus == MusicStatus.PLAY) {
pause();
} else {
play();
}
}
public void next() {
playAnimator();
selectMusicWithButton();
}
public void last() {
playAnimator();
selectMusicWithButton();
}

@ -34,16 +34,19 @@
android:id="@+id/tv_song"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="青茫"
android:textColor="@color/white"
android:textSize="18sp" />
android:textSize="18sp"
android:ellipsize="end"
android:maxEms="15"
android:singleLine="true"/>
<TextView
android:id="@+id/tv_singer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="白敬亭、李宏毅、丁冠森、赵文龙"
android:ellipsize="end"
android:maxEms="15"
android:textColor="@color/white_easy" />
</LinearLayout>
</RelativeLayout>

Loading…
Cancel
Save