From 06d89b44899cc0edf54df273d11fcde1034273d1 Mon Sep 17 00:00:00 2001 From: kHRYSTAL <723526676@qq.com> Date: Sun, 26 Mar 2017 03:12:49 +0800 Subject: [PATCH 1/5] support '/n' --- .gitignore | 1 + .../library/ExpandableTextView.java | 94 ++++++++++--------- sample/.gitignore | 1 + sample/src/main/res/layout/activity_main.xml | 2 +- sample/src/main/res/values/strings.xml | 6 +- 5 files changed, 57 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index c6cbe56..4c16a86 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ .DS_Store /build /captures +/.idea/ diff --git a/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java b/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java index dd00c7c..16606ef 100644 --- a/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java +++ b/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java @@ -244,61 +244,59 @@ private CharSequence getNewTextByConfig(){ mTextLineCount = -1; switch (mCurrState){ case STATE_SHRINK: { +// update by kHRYSTAL fix support '\n' mLayout = new DynamicLayout(mOrigText, mTextPaint, mLayoutWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + //计算共有多少行 mTextLineCount = mLayout.getLineCount(); - + //如果文字行数小于限制行数 那么直接返回 不需要折叠 if (mTextLineCount <= mMaxLinesOnShrink) { return mOrigText; } - int indexEnd = getValidLayout().getLineEnd(mMaxLinesOnShrink - 1); - int indexStart = getValidLayout().getLineStart(mMaxLinesOnShrink - 1); - int indexEndTrimmed = indexEnd - - getLengthOfString(mEllipsisHint) - - (mShowToExpandHint ? getLengthOfString(mToExpandHint) + getLengthOfString(mGapToExpandHint) : 0); - if (indexEndTrimmed <= 0) { - return mOrigText.subSequence(0, indexEnd); + + if (mOrigText == null || mOrigText.length() == 0) { + return mOrigText; } - int remainWidth = getValidLayout().getWidth() - - (int) (mTextPaint.measureText(mOrigText.subSequence(indexStart, indexEndTrimmed).toString()) + 0.5); + // 计算限制最大行的第一个字index + int start = getValidLayout().getLineStart(mMaxLinesOnShrink - 1); + // 计算限制最大行的最后一个字index 有可能是换行符 有可能是"" 需要递减 + int end = getValidLayout().getLineEnd(mMaxLinesOnShrink - 1); + // 获取最后一行文字内容 + CharSequence content = mOrigText.subSequence(start, end); + + float moreWidth = getPaint().measureText(mToExpandHint, 0, mToExpandHint.length()); + float gapWidth = getPaint().measureText(mGapToExpandHint, 0, mGapToExpandHint.length()); + float maxWidth = getValidLayout().getWidth() - moreWidth - gapWidth; + // 获取一行显示的最大长度 + getPaint().setSubpixelText(true); + // TODO 注意改方法如果设置宽度为wrap_content len会返回0 导致错误异常!! + int len = getPaint().breakText(content, 0, content.length(), true, maxWidth, null); + len = Math.min(len, end); + + // 判断这行最后一个字是不是换行符 如果是 左移最大index + if (content.charAt(len - 1) == '\n') { + len -= 1; + } + // 计算最后一行的剩余空间 + int endSpaceWidth = getValidLayout().getWidth() - + (int) (mTextPaint.measureText(mOrigText.subSequence(start, start + len).toString()) + 0.5); + // 计算 "... 全文"所占空间 float widthTailReplaced = mTextPaint.measureText(getContentOfString(mEllipsisHint) - + (mShowToExpandHint ? (getContentOfString(mToExpandHint) + getContentOfString(mGapToExpandHint)) : "")); - - int indexEndTrimmedRevised = indexEndTrimmed; - if (remainWidth > widthTailReplaced) { - int extraOffset = 0; - int extraWidth = 0; - while (remainWidth > widthTailReplaced + extraWidth) { - extraOffset++; - if (indexEndTrimmed + extraOffset <= mOrigText.length()) { - extraWidth = (int) (mTextPaint.measureText( - mOrigText.subSequence(indexEndTrimmed, indexEndTrimmed + extraOffset).toString()) + 0.5); - } else { - break; + + (mShowToExpandHint ? (getContentOfString(mToExpandHint) + getContentOfString(mGapToExpandHint)) + 0.5 : "")); + // 如果最后一行剩余空间小于 ... 全文所占空间 需要递减文字长度 + if (endSpaceWidth <= widthTailReplaced) { + while (endSpaceWidth <= widthTailReplaced) { + len = len - 1; + if (content.charAt(len - 1) == '\n') { + len = len - 1; } + endSpaceWidth = getValidLayout().getWidth() - + (int) (mTextPaint.measureText(mOrigText.subSequence(start, start + len).toString())); } - indexEndTrimmedRevised += extraOffset - 1; - } else { - int extraOffset = 0; - int extraWidth = 0; - while (remainWidth + extraWidth < widthTailReplaced) { - extraOffset--; - if (indexEndTrimmed + extraOffset > indexStart) { - extraWidth = (int) (mTextPaint.measureText(mOrigText.subSequence(indexEndTrimmed + extraOffset, indexEndTrimmed).toString()) + 0.5); - } else { - break; - } - } - indexEndTrimmedRevised += extraOffset; } + return createShrinkText(mOrigText.subSequence(0, start + len)); +// update end - SpannableStringBuilder ssbShrink = new SpannableStringBuilder(mOrigText, 0, indexEndTrimmedRevised) - .append(mEllipsisHint); - if (mShowToExpandHint) { - ssbShrink.append(getContentOfString(mGapToExpandHint) + getContentOfString(mToExpandHint)); - ssbShrink.setSpan(mTouchableSpan, ssbShrink.length() - getLengthOfString(mToExpandHint), ssbShrink.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - return ssbShrink; } case STATE_EXPAND: { if (!mShowToShrinkHint) { @@ -320,6 +318,16 @@ private CharSequence getNewTextByConfig(){ return mOrigText; } + private Spanned createShrinkText(CharSequence limitContent) { + SpannableStringBuilder ssShrink = new SpannableStringBuilder(limitContent) + .append(mEllipsisHint); + if (mShowToExpandHint) { + ssShrink.append(mGapToExpandHint).append(mToExpandHint); + ssShrink.setSpan(mTouchableSpan, ssShrink.length() - getLengthOfString(mToExpandHint), ssShrink.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return ssShrink; + } + public void setExpandListener(OnExpandListener listener){ mOnExpandListener = listener; } diff --git a/sample/.gitignore b/sample/.gitignore index 796b96d..92910a0 100644 --- a/sample/.gitignore +++ b/sample/.gitignore @@ -1 +1,2 @@ /build +/.idea/ diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index b0341d1..a9ce2d2 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -36,7 +36,7 @@ 原始文本: 实际效果: update list - 千古江山,英雄无觅,孙仲谋处。舞榭歌台,风流总被、雨打风吹去。斜阳草树,寻常巷陌,人道寄奴曾住。想当年,金戈铁马,气吞万里如虎。元嘉草草,封狼居胥,赢得仓皇北顾。四十三年,望中犹记,烽火扬州路。可堪回首,佛狸祠下,一片神鸦社鼓。凭谁问:廉颇老矣,尚能饭否? + aaa\nbbb\nccc\n - 1.醉里挑灯看剑,梦回吹角连营。八百里分麾下炙,五十弦翻塞外声。沙场秋点兵。马作的卢飞快,弓如霹雳弦惊。了却君王天下事,赢得生前身后名。可怜白发生。 + aaa\n\n\nccc\n 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 3.淮左名都,竹西佳处,解鞍少驻初程。过春风十里。尽荠麦青青。自胡马窥江去后,废池乔木,犹厌言兵。渐黄昏,清角吹寒。都在空城。杜郎俊赏,算而今、重到须惊。纵豆蔻词工,青楼梦好,难赋深情。二十四桥仍在,波心荡、冷月无声。念桥边红药,年年知为谁生。 4.春花秋月何时了?往事知多少。小楼昨夜又东风,故国不堪回首月明中。雕栏玉砌应犹在,只是朱颜改。问君能有几多愁?恰似一江春水向东流。 @@ -25,7 +25,7 @@ - 1.醉里挑灯看剑,梦回吹角连营。八百里分麾下炙,五十弦翻塞外声。沙场秋点兵。马作的卢飞快,弓如霹雳弦惊。了却君王天下事,赢得生前身后名。可怜白发生。 + aaa\n\n\nccc\n 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 3.淮左名都,竹西佳处,解鞍少驻初程。过春风十里。尽荠麦青青。自胡马窥江去后,废池乔木,犹厌言兵。渐黄昏,清角吹寒。都在空城。杜郎俊赏,算而今、重到须惊。纵豆蔻词工,青楼梦好,难赋深情。二十四桥仍在,波心荡、冷月无声。念桥边红药,年年知为谁生。 4.春花秋月何时了?往事知多少。小楼昨夜又东风,故国不堪回首月明中。雕栏玉砌应犹在,只是朱颜改。问君能有几多愁?恰似一江春水向东流。 From 1a9fc70e18b0a1427be7b54315916bba0d5248a7 Mon Sep 17 00:00:00 2001 From: kHRYSTAL <723526676@qq.com> Date: Sun, 26 Mar 2017 03:14:15 +0800 Subject: [PATCH 2/5] delete .idea files --- .idea/.name | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .idea/.name diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 3c76e38..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -ExpandableTextView \ No newline at end of file From 1508b791f272fbb13cf770d1e68cfcb1f0056861 Mon Sep 17 00:00:00 2001 From: kHRYSTAL <723526676@qq.com> Date: Tue, 28 Mar 2017 13:46:35 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E8=A7=A3=E5=86=B3touch=20span=E6=97=B6=20t?= =?UTF-8?q?extview=E7=82=B9=E5=87=BB=E4=BA=8B=E4=BB=B6=E4=B9=9F=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/gradle.xml | 8 +-- .idea/misc.xml | 60 ++++++++++++++++++- .../library/ExpandableTextView.java | 19 ++++-- .../expandabletextview/ActivityMain.java | 9 +++ sample/src/main/res/layout/activity_main.xml | 1 + 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/.idea/gradle.xml b/.idea/gradle.xml index acc87bb..903e3d4 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,13 +12,7 @@ - + diff --git a/.idea/misc.xml b/.idea/misc.xml index efbef40..0926f21 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,48 @@ + + + + + + + + + + + + + + + + + + Android + + + + + @@ -16,11 +59,24 @@ + + - + + + + + + + + - 1.8 - + diff --git a/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java b/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java index b404374..82f9631 100644 --- a/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java +++ b/library/src/main/java/cn/carbs/android/expandabletextview/library/ExpandableTextView.java @@ -85,7 +85,7 @@ public class ExpandableTextView extends TextView{ private ExpandableClickListener mExpandableClickListener; private OnExpandListener mOnExpandListener; // this field must control in outside when touch in recyclerView such as write in POJO - private boolean isExpandClick; + private boolean isSpanHandle; public ExpandableTextView(Context context) { super(context); @@ -334,12 +334,12 @@ public void setExpandListener(OnExpandListener listener){ mOnExpandListener = listener; } - public boolean isExpandClicked() { - return isExpandClick; + public boolean isSpanHandle() { + return isSpanHandle; } - public void setExpandIsClicked(boolean isExpandClicked) { - this.isExpandClick = isExpandClicked; + public void setIsSpanHandle(boolean isSpanHandle) { + this.isSpanHandle = isSpanHandle; } private Layout getValidLayout(){ @@ -347,7 +347,7 @@ private Layout getValidLayout(){ } private void toggle(){ - isExpandClick = false; + isSpanHandle = false; switch (mCurrState){ case STATE_SHRINK: mCurrState = STATE_EXPAND; @@ -396,7 +396,8 @@ public interface OnExpandListener{ private class ExpandableClickListener implements View.OnClickListener{ @Override public void onClick(View view) { - toggle(); + if (!isSpanHandle) + toggle(); } } @@ -461,7 +462,7 @@ public void setPressed(boolean isSelected) { @Override public void onClick(View widget) { - toggle(); + toggle(); } @Override @@ -496,12 +497,12 @@ public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent if (event.getAction() == MotionEvent.ACTION_DOWN) { mPressedSpan = getPressedSpan(textView, spannable, event); if (mPressedSpan != null) { - isExpandClick = true; + isSpanHandle = true; mPressedSpan.setPressed(true); Selection.setSelection(spannable, spannable.getSpanStart(mPressedSpan), spannable.getSpanEnd(mPressedSpan)); } else { - isExpandClick = false; + isSpanHandle = false; } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { TouchableSpan touchedSpan = getPressedSpan(textView, spannable, event); @@ -509,17 +510,17 @@ public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent mPressedSpan.setPressed(false); mPressedSpan = null; Selection.removeSelection(spannable); - isExpandClick = true; + isSpanHandle = true; } else { - isExpandClick = false; + isSpanHandle = false; } } else { if (mPressedSpan != null) { mPressedSpan.setPressed(false); super.onTouchEvent(textView, spannable, event); - isExpandClick = true; + isSpanHandle = true; } else { - isExpandClick = false; + isSpanHandle = false; } mPressedSpan = null; Selection.removeSelection(spannable); diff --git a/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityListView.java b/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityListView.java index 7166e96..c4cf127 100644 --- a/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityListView.java +++ b/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityListView.java @@ -3,6 +3,7 @@ import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; +import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; @@ -79,7 +80,9 @@ private void inflateListViews(){ mFlag = !mFlag; } - class TheBaseAdapter extends BaseAdapter implements ExpandableTextView.OnExpandListener{ + class TheBaseAdapter extends BaseAdapter + implements ExpandableTextView.OnExpandListener + { private SparseArray mPositionsAndStates = new SparseArray<>(); private List mList; @@ -132,8 +135,7 @@ public void run() { viewHolder.etv.setTag(position); viewHolder.etv.setExpandListener(this); Integer state = mPositionsAndStates.get(position); - - viewHolder.etv.updateForRecyclerView(content.toString(), etvWidth, state== null ? 0 : state);//第一次getview时肯定为etvWidth为0 + viewHolder.etv.updateForRecyclerView(content.toString(), etvWidth, state == null ? 0 : state);//第一次getview时肯定为etvWidth为0 return convertView; } @@ -142,15 +144,16 @@ public void run() { public void onExpand(ExpandableTextView view) { Object obj = view.getTag(); if(obj != null && obj instanceof Integer){ - mPositionsAndStates.put((Integer)obj, view.getExpandState()); + mPositionsAndStates.put((Integer)obj, 1); } } - +// @Override public void onShrink(ExpandableTextView view) { Object obj = view.getTag(); if(obj != null && obj instanceof Integer){ - mPositionsAndStates.put((Integer)obj, view.getExpandState()); + mPositionsAndStates.put((Integer)obj, 0); + mListView.setSelection((Integer) obj); } } } diff --git a/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityMain.java b/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityMain.java index be0a4a0..843a54c 100644 --- a/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityMain.java +++ b/sample/src/main/java/cn/carbs/android/expandabletextview/ActivityMain.java @@ -35,13 +35,13 @@ protected void onCreate(Bundle savedInstanceState) { mBtnUpdateText = (Button)this.findViewById(R.id.button_update_text); mBtnToListView = (Button)this.findViewById(R.id.button_to_list_view); mETV = (ExpandableTextView)this.findViewById(R.id.etv); + // 测试添加OnClickListener的情况,功能正常。添加外部的onClick事件后,原来的点击toggle功能自动屏蔽, + // 点击尾部的ClickableSpan仍然有效 mETV.setOnClickListener(this); mBtnUpdateText.setOnClickListener(this); mBtnToListView.setOnClickListener(this); - // 测试添加OnClickListener的情况,功能正常。添加外部的onClick事件后,原来的点击toggle功能自动屏蔽, - // 点击尾部的ClickableSpan仍然有效 /*mETV.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { @@ -70,11 +70,7 @@ public void onClick(View view) { updateText(); break; case R.id.etv: - if (mETV.isExpandClicked()) { - - } else { - Toast.makeText(ActivityMain.this, "show", Toast.LENGTH_SHORT).show(); - } + Toast.makeText(ActivityMain.this, "is span handle:" + mETV.isSpanHandle(), Toast.LENGTH_SHORT).show(); break; } } diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index 427978e..244db75 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -5,10 +5,20 @@ 原始文本: 实际效果: update list - aaa\nbbb\nccc\n + \n庭院深深深几许,\n云窗雾阁春迟。\n为谁憔悴损芳姿。\n夜来清梦好 aaa\n\n\nccc\n - 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 3.淮左名都,竹西佳处,解鞍少驻初程。过春风十里。尽荠麦青青。自胡马窥江去后,废池乔木,犹厌言兵。渐黄昏,清角吹寒。都在空城。杜郎俊赏,算而今、重到须惊。纵豆蔻词工,青楼梦好,难赋深情。二十四桥仍在,波心荡、冷月无声。念桥边红药,年年知为谁生。 4.春花秋月何时了?往事知多少。小楼昨夜又东风,故国不堪回首月明中。雕栏玉砌应犹在,只是朱颜改。问君能有几多愁?恰似一江春水向东流。 5.无言独上西楼,月如钩。寂寞梧桐深院锁清秋。剪不断,理还乱,是离愁。别是一般滋味在心头。 @@ -26,7 +36,27 @@ aaa\n\n\nccc\n - 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 + 2.庭院深深深几许,云窗雾阁春迟。为谁憔悴损芳姿。夜来清梦好,应是发南枝。玉瘦檀轻无限恨,南楼羌管休吹。浓香吹尽有谁知。暖风迟日也,别到杏花肥。 3.淮左名都,竹西佳处,解鞍少驻初程。过春风十里。尽荠麦青青。自胡马窥江去后,废池乔木,犹厌言兵。渐黄昏,清角吹寒。都在空城。杜郎俊赏,算而今、重到须惊。纵豆蔻词工,青楼梦好,难赋深情。二十四桥仍在,波心荡、冷月无声。念桥边红药,年年知为谁生。 4.春花秋月何时了?往事知多少。小楼昨夜又东风,故国不堪回首月明中。雕栏玉砌应犹在,只是朱颜改。问君能有几多愁?恰似一江春水向东流。 5.无言独上西楼,月如钩。寂寞梧桐深院锁清秋。剪不断,理还乱,是离愁。别是一般滋味在心头。