自定義控件LrcView
mport android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.widget.OverScroller;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import com.carocean.R;
import com.carocean.media.constants.MediaScanConstans;
import com.carocean.media.service.LrcContent;
public class LrcView extends View {
private List<LrcContent> mLrcData;
private TextPaint mTextPaint;
private String mDefaultContent;
private int mCurrentLine;
private float mOffset;
private float mLastMotionX;
private float mLastMotionY;
private int mScaledTouchSlop;
private OverScroller mOverScroller;
private VelocityTracker mVelocityTracker;
private int mMaximumFlingVelocity;
private int mMinimumFlingVelocity;
private float mLrcTextSize;
private float mLrcLineSpaceHeight;
private int mTouchDelay;
private int mNormalColor;
private int mCurrentPlayLineColor;
private float mNoLrcTextSize;
private int mNoLrcTextColor;
// 是否拖拽中,否的話響應onClick事件
private boolean isDragging;
// 用戶開始操作
private boolean isUserScroll;
private boolean isAutoAdjustPosition = true;
private Drawable mPlayDrawable;
private boolean isShowTimeIndicator;
private Rect mPlayRect;
private Drawable mLineDrawable;
private Rect mLineRect;
private Paint mIndicatorPaint;
private float mIndicatorLineWidth;
private float mIndicatorTextSize;
private int mCurrentIndicateLineTextColor;
private int mIndicatorLineColor;
private float mIndicatorMargin;
private float mIconLineGap;
private float mIconWidth;
private float mIconHeight;
private float mLineWidth;
private float mLineHeight;
private boolean isEnableShowIndicator = true;
private int mIndicatorTextColor;
private int mIndicatorTouchDelay;
private boolean isCurrentTextBold;
private boolean isLrcIndicatorTextBold;
public LrcView(Context context) {
this(context, null);
}
public LrcView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LrcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LrcView);
mLrcTextSize = typedArray.getDimension(R.styleable.LrcView_lrcTextSize, sp2px(context, 26));
mLrcLineSpaceHeight = typedArray.getDimension(R.styleable.LrcView_lrcLineSpaceSize, dp2px(context, 20));
mTouchDelay = typedArray.getInt(R.styleable.LrcView_lrcTouchDelay, 3500);
mIndicatorTouchDelay = typedArray.getInt(R.styleable.LrcView_indicatorTouchDelay, 2500);
mNormalColor = typedArray.getColor(R.styleable.LrcView_lrcNormalTextColor, Color.YELLOW);
mCurrentPlayLineColor = typedArray.getColor(R.styleable.LrcView_lrcCurrentTextColor, Color.RED);
mNoLrcTextSize = typedArray.getDimension(R.styleable.LrcView_noLrcTextSize, dp2px(context, 26));
mNoLrcTextColor = typedArray.getColor(R.styleable.LrcView_noLrcTextColor, Color.WHITE); // 拖動橫線
mIndicatorLineWidth = typedArray.getDimension(R.styleable.LrcView_indicatorLineHeight, dp2px(context, 0.5f));
mIndicatorTextSize = typedArray.getDimension(R.styleable.LrcView_indicatorTextSize, sp2px(context, 26));
mIndicatorTextColor = typedArray.getColor(R.styleable.LrcView_indicatorTextColor, Color.BLACK);
mCurrentIndicateLineTextColor = typedArray.getColor(R.styleable.LrcView_currentIndicateLrcColor, Color.GREEN);
mIndicatorLineColor = typedArray.getColor(R.styleable.LrcView_indicatorLineColor, Color.WHITE);
mIndicatorMargin = typedArray.getDimension(R.styleable.LrcView_indicatorStartEndMargin, dp2px(context, 205));
mIconLineGap = typedArray.getDimension(R.styleable.LrcView_iconLineGap, dp2px(context, 3));
mIconWidth = typedArray.getDimension(R.styleable.LrcView_playIconWidth, dp2px(context, 52));
mIconHeight = typedArray.getDimension(R.styleable.LrcView_playIconHeight, dp2px(context, 52));
mPlayDrawable = typedArray.getDrawable(R.styleable.LrcView_playIcon);
mLineWidth = typedArray.getDimension(R.styleable.LrcView_playIconWidth, dp2px(context, 454));
mLineHeight = typedArray.getDimension(R.styleable.LrcView_playIconHeight, dp2px(context, 4));
mLineDrawable = typedArray.getDrawable(R.styleable.LrcView_playLineIcon);
isCurrentTextBold = typedArray.getBoolean(R.styleable.LrcView_isLrcCurrentTextBold, false);
isLrcIndicatorTextBold = typedArray.getBoolean(R.styleable.LrcView_isLrcIndicatorTextBold, false);
typedArray.recycle();
setupConfigs(context);
}
private void setupConfigs(Context context) {
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumFlingVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
mMinimumFlingVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
mOverScroller = new OverScroller(context, new DecelerateInterpolator());
mOverScroller.setFriction(0.1f);
// ViewConfiguration.getScrollFriction(); 默認摩擦力 0.015f
mTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(mLrcTextSize);
mDefaultContent = context.getResources().getString(R.string.media_music_not_found_lrc_file);
mIndicatorPaint = new Paint();
mIndicatorPaint.setAntiAlias(true);
mIndicatorPaint.setStrokeWidth(mIndicatorLineWidth);
mIndicatorPaint.setColor(mIndicatorLineColor);
mPlayRect = new Rect();
mLineRect = new Rect();
mIndicatorPaint.setTextSize(mIndicatorTextSize);
}
private int getLrcWidth() {
return getWidth() - getPaddingLeft() - getPaddingRight();
}
private int getLrcHeight() {
return getHeight();
}
private boolean isLrcEmpty() {
return mLrcData == null || getLrcCount() == 0;
}
private int getLrcCount() {
return mLrcData.size();
}
public void setLrcData(List<LrcContent> lrcData) {
resetView(mDefaultContent);
mLrcData = lrcData;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isLrcEmpty()) {
drawEmptyText(canvas);
return;
}
int indicatePosition = getIndicatePosition();
mTextPaint.setTextSize(mLrcTextSize);
mTextPaint.setTextAlign(Paint.Align.CENTER);
float y = getLrcHeight() / 2f;
float x = getLrcWidth() / 2f + getPaddingLeft();
for (int i = 0; i < getLrcCount(); i++) {
if (i > 0) {
y += (getTextHeight(i - 1) + getTextHeight(i)) / 2f + mLrcLineSpaceHeight;
}
if (mCurrentLine == i) {
mTextPaint.setColor(mCurrentPlayLineColor);
mTextPaint.setFakeBoldText(isCurrentTextBold);
} else if (indicatePosition == i && isShowTimeIndicator) {
mTextPaint.setFakeBoldText(isLrcIndicatorTextBold);
mTextPaint.setColor(mCurrentIndicateLineTextColor);
} else {
mTextPaint.setFakeBoldText(false);
mTextPaint.setColor(mNormalColor);
}
drawLrc(canvas, x, y, i);
}
if (isShowTimeIndicator) {
mPlayDrawable.draw(canvas);
mLineDrawable.draw(canvas);
long time = mLrcData.get(indicatePosition).getLrcTime();
float timeWidth = mIndicatorPaint.measureText(MediaScanConstans.formatTime(time));
// mIndicatorPaint.setColor(mIndicatorLineColor);
// canvas.drawLine(30 + timeWidth * 1.1f, (getHeight() / 2f), mPlayRect.left -
// timeWidth * 0.1f,
// getHeight() / 2f, mIndicatorPaint);
int baseX = 30;
float baseline = getHeight() / 2f - (mIndicatorPaint.descent() - mIndicatorPaint.ascent()) / 2
- mIndicatorPaint.ascent();
mIndicatorPaint.setColor(mIndicatorTextColor);
canvas.drawText(MediaScanConstans.formatTime(time), baseX, baseline, mIndicatorPaint);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mLineRect.left = 120;
mLineRect.top = (int) (getHeight() / 2 - mLineHeight / 2);
mLineRect.right = (int) (mLineRect.left + mLineWidth);
mLineRect.bottom = (int) (mLineRect.top + mLineHeight);
mLineDrawable.setBounds(mLineRect);
int mX = (int) (getWidth() - mIconWidth - 60);
mPlayRect.left = mX;
mPlayRect.top = (int) (getHeight() / 2 - mIconHeight / 2);
mPlayRect.right = (int) (mPlayRect.left + mIconWidth);
mPlayRect.bottom = (int) (mPlayRect.top + mIconHeight);
mPlayDrawable.setBounds(mPlayRect);
}
}
private HashMap<String, StaticLayout> mLrcMap = new HashMap<String, StaticLayout>();
private void drawLrc(Canvas canvas, float x, float y, int i) {
String text = mLrcData.get(i).getLrcStr();
StaticLayout staticLayout = mLrcMap.get(text);
if (staticLayout == null) {
mTextPaint.setTextSize(mLrcTextSize);
staticLayout = new StaticLayout(text, mTextPaint, getLrcWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f,
false);
mLrcMap.put(text, staticLayout);
}
canvas.save();
canvas.translate(x, y - staticLayout.getHeight() / 2f - mOffset);
staticLayout.draw(canvas);
canvas.restore();
}
// 中間空文字
private void drawEmptyText(Canvas canvas) {
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setColor(mNoLrcTextColor);
mTextPaint.setTextSize(mNoLrcTextSize);
canvas.save();
Configuration con = this.getResources().getConfiguration();
String language = con.locale.getLanguage();
StaticLayout staticLayout = null;
if (language.equals("fa")) {
staticLayout = new StaticLayout(mDefaultContent, mTextPaint, getLrcWidth(), Layout.Alignment.ALIGN_OPPOSITE,
1f, 0f, false);
canvas.translate(getLrcWidth() / 2f, getLrcHeight() / 2f);
} else {
staticLayout = new StaticLayout(mDefaultContent, mTextPaint, getLrcWidth(), Layout.Alignment.ALIGN_NORMAL,
1f, 0f, false);
canvas.translate(getLrcWidth() / 2f + getPaddingLeft(), getLrcHeight() / 2f);
}
staticLayout.draw(canvas);
canvas.restore();
}
public void updateTime(long time) {
if (isLrcEmpty()) {
return;
}
int linePosition = getUpdateTimeLinePosition(time);
if (mCurrentLine != linePosition) {
mCurrentLine = linePosition;
if (isUserScroll) {
invalidateView();
return;
}
ViewCompat.postOnAnimation(LrcView.this, mScrollRunnable);
}
}
private int getUpdateTimeLinePosition(long time) {
int linePos = 0;
for (int i = 0; i < getLrcCount(); i++) {
LrcContent lrc = mLrcData.get(i);
if (time >= lrc.getLrcTime()) {
if (i == getLrcCount() - 1) {
linePos = getLrcCount() - 1;
} else if (time < mLrcData.get(i + 1).getLrcTime()) {
linePos = i;
break;
}
}
}
return linePos;
}
private Runnable mScrollRunnable = new Runnable() {
@Override
public void run() {
isUserScroll = false;
scrollToPosition(mCurrentLine);
}
};
private Runnable mHideIndicatorRunnable = new Runnable() {
@Override
public void run() {
isShowTimeIndicator = false;
invalidateView();
}
};
private void scrollToPosition(int linePosition) {
float scrollY = getItemOffsetY(linePosition);
final ValueAnimator animator = ValueAnimator.ofFloat(mOffset, scrollY);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mOffset = (Float) animation.getAnimatedValue();
invalidateView();
}
});
animator.setDuration(300);
animator.start();
}
public int getIndicatePosition() {
int pos = 0;
float min = Float.MAX_VALUE;
// itemOffset 和 mOffset 最小即當前位置
for (int i = 0; i < mLrcData.size(); i++) {
float offsetY = getItemOffsetY(i);
float abs = Math.abs(offsetY - mOffset);
if (abs < min) {
min = abs;
pos = i;
}
}
return pos;
}
private float getItemOffsetY(int linePosition) {
float tempY = 0;
for (int i = 1; i <= linePosition; i++) {
tempY += (getTextHeight(i - 1) + getTextHeight(i)) / 2 + mLrcLineSpaceHeight;
}
return tempY;
}
private HashMap<String, StaticLayout> mStaticLayoutHashMap = new HashMap<String, StaticLayout>();
private float getTextHeight(int linePosition) {
String text = mLrcData.get(linePosition).getLrcStr();
StaticLayout staticLayout = mStaticLayoutHashMap.get(text);
if (staticLayout == null) {
mTextPaint.setTextSize(mLrcTextSize);
staticLayout = new StaticLayout(text, mTextPaint, getLrcWidth(), Layout.Alignment.ALIGN_NORMAL, 1f, 0f,
false);
mStaticLayoutHashMap.put(text, staticLayout);
}
return staticLayout.getHeight();
}
private boolean overScrolled() {
return mOffset > getItemOffsetY(getLrcCount() - 1) || mOffset < 0;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isLrcEmpty()) {
return super.onTouchEvent(event);
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
removeCallbacks(mScrollRunnable);
removeCallbacks(mHideIndicatorRunnable);
if (!mOverScroller.isFinished()) {
mOverScroller.abortAnimation();
}
mLastMotionX = event.getX();
mLastMotionY = event.getY();
isUserScroll = true;
isDragging = false;
break;
case MotionEvent.ACTION_MOVE:
float moveY = event.getY() - mLastMotionY;
if (Math.abs(moveY) > mScaledTouchSlop) {
isDragging = true;
isShowTimeIndicator = isEnableShowIndicator;
}
if (isDragging) {
// if (mOffset < 0) {
// mOffset = Math.max(mOffset, -getTextHeight(0) - mLrcLineSpaceHeight);
// }
float maxHeight = getItemOffsetY(getLrcCount() - 1);
// if (mOffset > maxHeight) {
// mOffset = Math.min(mOffset, maxHeight + getTextHeight(getLrcCount() - 1) +
// mLrcLineSpaceHeight);
// }
if (mOffset < 0 || mOffset > maxHeight) {
moveY /= 3.5f;
}
mOffset -= moveY;
mLastMotionY = event.getY();
invalidateView();
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!isDragging && (!isShowTimeIndicator || !onClickPlayButton(event))) {
isShowTimeIndicator = false;
invalidateView();
performClick();
}
handleActionUp(event);
break;
}
// return isDragging || super.onTouchEvent(event);
return true;
}
private void handleActionUp(MotionEvent event) {
if (isEnableShowIndicator) {
ViewCompat.postOnAnimationDelayed(LrcView.this, mHideIndicatorRunnable, mIndicatorTouchDelay);
}
if (isShowTimeIndicator && mPlayRect != null && onClickPlayButton(event)) {
isShowTimeIndicator = false;
invalidateView();
if (mOnPlayIndicatorLineListener != null) {
mOnPlayIndicatorLineListener.onPlay(mLrcData.get(getIndicatePosition()).getLrcTime(),
mLrcData.get(getIndicatePosition()).getLrcStr());
}
}
if (overScrolled() && mOffset < 0) {
scrollToPosition(0);
if (isAutoAdjustPosition) {
ViewCompat.postOnAnimationDelayed(LrcView.this, mScrollRunnable, mTouchDelay);
}
return;
}
if (overScrolled() && mOffset > getItemOffsetY(getLrcCount() - 1)) {
scrollToPosition(getLrcCount() - 1);
if (isAutoAdjustPosition) {
ViewCompat.postOnAnimationDelayed(LrcView.this, mScrollRunnable, mTouchDelay);
}
return;
}
mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
float yVelocity = mVelocityTracker.getYVelocity();
float absYVelocity = Math.abs(yVelocity);
if (absYVelocity > mMinimumFlingVelocity) {
mOverScroller.fling(0, (int) mOffset, 0, (int) (-yVelocity), 0, 0, 0,
(int) getItemOffsetY(getLrcCount() - 1), 0, (int) getTextHeight(0));
invalidateView();
}
releaseVelocityTracker();
if (isAutoAdjustPosition) {
ViewCompat.postOnAnimationDelayed(LrcView.this, mScrollRunnable, mTouchDelay);
}
}
private boolean onClickPlayButton(MotionEvent event) {
float left = mPlayRect.left;
float right = mPlayRect.right;
float top = mPlayRect.top;
float bottom = mPlayRect.bottom;
float x = event.getX();
float y = event.getY();
return mLastMotionX > left && mLastMotionX < right && mLastMotionY > top && mLastMotionY < bottom && x > left
&& x < right && y > top && y < bottom;
}
@Override
public void computeScroll() {
super.computeScroll();
if (mOverScroller.computeScrollOffset()) {
mOffset = mOverScroller.getCurrY();
invalidateView();
}
}
private void releaseVelocityTracker() {
if (null != mVelocityTracker) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
public void resetView(String defaultContent) {
if (mLrcData != null) {
mLrcData.clear();
}
mLrcMap.clear();
mStaticLayoutHashMap.clear();
mCurrentLine = 0;
mOffset = 0;
isUserScroll = false;
isDragging = false;
mDefaultContent = defaultContent;
removeCallbacks(mScrollRunnable);
invalidate();
}
@Override
public boolean performClick() {
return super.performClick();
}
public int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
context.getResources().getDisplayMetrics());
}
public int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
context.getResources().getDisplayMetrics());
}
/**
* 暫停(手動滑動歌詞後,不再自動回滾至當前播放位置)
*/
public void pause() {
isAutoAdjustPosition = false;
invalidateView();
}
/**
* 恢復(繼續自動回滾)
*/
public void resume() {
isAutoAdjustPosition = true;
ViewCompat.postOnAnimationDelayed(LrcView.this, mScrollRunnable, mTouchDelay);
invalidateView();
}
private void invalidateView() {
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
invalidate();
} else {
postInvalidate();
}
}
/*------------------Config-------------------*/
private OnPlayIndicatorLineListener mOnPlayIndicatorLineListener;
public void setOnPlayIndicatorLineListener(OnPlayIndicatorLineListener onPlayIndicatorLineListener) {
mOnPlayIndicatorLineListener = onPlayIndicatorLineListener;
}
public interface OnPlayIndicatorLineListener {
void onPlay(long time, String content);
}
public void setEmptyContent(String defaultContent) {
mDefaultContent = defaultContent;
invalidateView();
}
public void setLrcTextSize(float lrcTextSize) {
mLrcTextSize = lrcTextSize;
invalidateView();
}
public void setLrcLineSpaceHeight(float lrcLineSpaceHeight) {
mLrcLineSpaceHeight = lrcLineSpaceHeight;
invalidateView();
}
public void setTouchDelay(int touchDelay) {
mTouchDelay = touchDelay;
invalidateView();
}
public void setNormalColor(int normalColor) {
mNormalColor = normalColor;
invalidateView();
}
public void setCurrentPlayLineColor(int currentPlayLineColor) {
mCurrentPlayLineColor = currentPlayLineColor;
invalidateView();
}
public void setNoLrcTextSize(float noLrcTextSize) {
mNoLrcTextSize = noLrcTextSize;
invalidateView();
}
public void setNoLrcTextColor(int noLrcTextColor) {
mNoLrcTextColor = noLrcTextColor;
invalidateView();
}
public void setIndicatorLineWidth(float indicatorLineWidth) {
mIndicatorLineWidth = indicatorLineWidth;
invalidateView();
}
public void setIndicatorTextSize(float indicatorTextSize) {
// mIndicatorTextSize = indicatorTextSize;
mIndicatorPaint.setTextSize(indicatorTextSize);
invalidateView();
}
public void setCurrentIndicateLineTextColor(int currentIndicateLineTextColor) {
mCurrentIndicateLineTextColor = currentIndicateLineTextColor;
invalidateView();
}
public void setIndicatorLineColor(int indicatorLineColor) {
mIndicatorLineColor = indicatorLineColor;
invalidateView();
}
public void setIndicatorMargin(float indicatorMargin) {
mIndicatorMargin = indicatorMargin;
invalidateView();
}
public void setIconLineGap(float iconLineGap) {
mIconLineGap = iconLineGap;
invalidateView();
}
public void setIconWidth(float iconWidth) {
mIconWidth = iconWidth;
invalidateView();
}
public void setIconHeight(float iconHeight) {
mIconHeight = iconHeight;
invalidateView();
}
public void setEnableShowIndicator(boolean enableShowIndicator) {
isEnableShowIndicator = enableShowIndicator;
invalidateView();
}
public Drawable getPlayDrawable() {
return mPlayDrawable;
}
public void setPlayDrawable(Drawable playDrawable) {
mPlayDrawable = playDrawable;
mPlayDrawable.setBounds(mPlayRect);
invalidateView();
}
public void setIndicatorTextColor(int indicatorTextColor) {
mIndicatorTextColor = indicatorTextColor;
invalidateView();
}
public void setLrcCurrentTextBold(boolean bold) {
isCurrentTextBold = bold;
invalidateView();
}
public void setLrcIndicatorTextBold(boolean bold) {
isLrcIndicatorTextBold = bold;
invalidateView();
}
}
一些資源
<declare-styleable name="LrcView">
<attr name="lrcTextSize" format="dimension"/>
<attr name="lrcLineSpaceSize" format="dimension"/>
<attr name="lrcNormalTextColor" format="reference|color"/>
<attr name="lrcCurrentTextColor" format="reference|color"/>
<attr name="lrcTouchDelay" format="integer"/>
<attr name="noLrcTextSize" format="dimension"/>
<attr name="noLrcTextColor" format="reference|color"/>
<attr name="indicatorLineHeight" format="dimension"/>
<attr name="indicatorTextSize" format="dimension"/>
<attr name="indicatorTextColor" format="reference|color"/>
<attr name="currentIndicateLrcColor" format="reference|color"/>
<attr name="indicatorTouchDelay" format="integer"/>
<attr name="indicatorLineColor" format="reference|color"/>
<attr name="indicatorStartEndMargin" format="dimension"/>
<attr name="iconLineGap" format="dimension"/>
<attr name="playIconWidth" format="dimension"/>
<attr name="playIconHeight" format="dimension"/>
<attr name="playIcon" format="reference"/>
<attr name="playLineWidth" format="dimension"/>
<attr name="playLineHeight" format="dimension"/>
<attr name="playLineIcon" format="reference"/>
<attr name="isLrcCurrentTextBold" format="boolean"/>
<attr name="isLrcIndicatorTextBold" format="boolean"/>
</declare-styleable>
用法,圖片資源就不弄上來了
<com.carocean.media.LrcView
android:id="@+id/media_lrc_list"
android:layout_width="600dp"
android:layout_height="850dp"
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:gravity="center"
android:visibility="gone"
app:currentIndicateLrcColor="@color/red"
app:indicatorTextColor="@color/red"
app:isLrcCurrentTextBold="true"
app:isLrcIndicatorTextBold="true"
app:playIcon="@drawable/media_lrc_play_blue"
app:playLineIcon="@drawable/play_music_lrc_line" />