android文本輸入框 輸入完成自動(dòng)跳到下一個(gè)輸入框

定義文本框 輸入完一個(gè)自動(dòng)跳到下一個(gè)且獲取焦點(diǎn)缎讼,當(dāng)刪除一個(gè)自動(dòng)跳到前一個(gè)輸入框獲取焦點(diǎn)??

老規(guī)矩來(lái)一波效果圖:


新建NumberCodeView 繼承FrameLayout

public class NumberCodeView extends FrameLayout {

? ? private static final int[] STATE_NORMAL = {-android.R.attr.state_selected};

? ? private static final int[] STATE_SELECTED = {android.R.attr.state_selected};

? ? private static final int DEFAULT_TEXT_COLOR = 0xFFffffff;

? ? private static final int DEFAULT_TEXT_SIZE = 30;? //dp

? ? private static final int DEFAULT_FRAME_SIZE = 50;

? ? private static final int DEFAULT_FRAME_PADDING = 14;

? ? private static final int DEFAULT_CODE_LENGTH = 4;

? ? /**

? ? * 輸入View

? ? */

? ? private EditText mEditText;

? ? private int mLastIndex = 0;

? ? private int mCurIndex = 0;

? ? private int mCodeLength = 0;

? ? private Paint mCodeTextPaint;

? ? private Rect mTextRect;

? ? private String mCodeText = "";

? ? private int mFrameSize = -1;

? ? private int mFramePadding = -1;

? ? private int mCodeTextColor = -1;

? ? private int mCodeTextSize = -1;

? ? private int mNormalId = R.mipmap.verificate_code_normal;

? ? private int mSelectId = R.mipmap.verificate_code_selected;

? ? private boolean mShowSystemKeyboard = true;

? ? private @DrawableRes

? ? int mFrameDrawableId = -1;

? ? private SparseArrayCompat<Drawable> mInputDrawable = new SparseArrayCompat<>();

? ? private InputMethodManager mInputMethodManager;

? ? private OnNumberInputListener mOnNumberInputListener;

? ? private TextWatcher mTextWatcher = 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) {

? ? ? ? ? ? boolean isBack = mCodeText.length() > s.length();

? ? ? ? ? ? mLastIndex = mCurIndex;

? ? ? ? ? ? if (!TextUtils.isEmpty(s)) {

? ? ? ? ? ? ? ? mCodeText = s.toString();

? ? ? ? ? ? ? ? mCurIndex = isBack ? mCodeText.length() - 1 : mCodeText.length();

? ? ? ? ? ? ? ? mCurIndex = mCurIndex == mCodeLength ? mCurIndex - 1 : mCurIndex;

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? mCurIndex = 0;

? ? ? ? ? ? ? ? mCodeText = "";

? ? ? ? ? ? }

? ? ? ? ? ? setDrawableState(mLastIndex, STATE_NORMAL);

? ? ? ? ? ? if (mCodeText.length() == mCodeLength) {

? ? ? ? ? ? ? ? if (mOnNumberInputListener != null) {

? ? ? ? ? ? ? ? ? ? mOnNumberInputListener.onInputFinish();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? setDrawableState(mCurIndex, STATE_SELECTED);

? ? ? ? ? ? ? ? if (mOnNumberInputListener != null) {

? ? ? ? ? ? ? ? ? ? mOnNumberInputListener.onInputIng();

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? invalidate();

? ? ? ? }

? ? ? ? @Override

? ? ? ? public void afterTextChanged(Editable s) {

? ? ? ? }

? ? };

? ? public NumberCodeView(Context context) {

? ? ? ? this(context, null);

? ? }

? ? public NumberCodeView(Context context, AttributeSet attrs) {

? ? ? ? this(context, attrs, 0);

? ? }

? ? public NumberCodeView(Context context, AttributeSet attrs, int defStyleAttr) {

? ? ? ? super(context, attrs, defStyleAttr);

? ? ? ? PixelUtil pixelUtil = new PixelUtil(context);

? ? ? ? TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NumberCodeView);

? ? ? ? int size = typedArray.getIndexCount();

? ? ? ? if (size > 0) {

? ? ? ? ? ? for (int i = 0; i < size; i++) {

? ? ? ? ? ? ? ? int attr = typedArray.getIndex(i);

? ? ? ? ? ? ? ? switch (attr) {

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_codeTextColor:

? ? ? ? ? ? ? ? ? ? ? ? mCodeTextColor = typedArray.getColor(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_codeTextSize:

? ? ? ? ? ? ? ? ? ? ? ? mCodeTextSize = typedArray.getDimensionPixelSize(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_frameSize:

? ? ? ? ? ? ? ? ? ? ? ? mFrameSize = typedArray.getDimensionPixelSize(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_framePadding:

? ? ? ? ? ? ? ? ? ? ? ? mFramePadding = typedArray.getDimensionPixelOffset(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_codeLength:

? ? ? ? ? ? ? ? ? ? ? ? mCodeLength = typedArray.getInt(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_frameDrawableId:

? ? ? ? ? ? ? ? ? ? ? ? mFrameDrawableId = typedArray.getResourceId(attr, -1);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_normal:

? ? ? ? ? ? ? ? ? ? ? ? mNormalId = typedArray.getResourceId(attr, R.mipmap.verificate_code_normal);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ? ? case R.styleable.NumberCodeView_select:

? ? ? ? ? ? ? ? ? ? ? ? mSelectId = typedArray.getResourceId(attr, R.mipmap.verificate_code_selected);

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? typedArray.recycle();

? ? ? ? if (mCodeTextColor == -1) {

? ? ? ? ? ? mCodeTextColor = DEFAULT_TEXT_COLOR;

? ? ? ? }

? ? ? ? if (mCodeTextSize == -1) {

? ? ? ? ? ? mCodeTextSize = pixelUtil.dp2px(DEFAULT_TEXT_SIZE);

? ? ? ? }

? ? ? ? if (mFrameSize == -1) {

? ? ? ? ? ? mFrameSize = pixelUtil.dp2px(DEFAULT_FRAME_SIZE);

? ? ? ? }

? ? ? ? if (mFramePadding == -1) {

? ? ? ? ? ? mFramePadding = pixelUtil.dp2px(DEFAULT_FRAME_PADDING);

? ? ? ? }

? ? ? ? if (mCodeLength <= 0) {

? ? ? ? ? ? mCodeLength = DEFAULT_CODE_LENGTH;

? ? ? ? }

? ? ? ? mTextRect = new Rect();

? ? ? ? mInputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

? ? ? ? initEditText();

? ? ? ? initTextPaint();

? ? ? ? initStateListDrawable();

? ? ? ? setWillNotDraw(false);

? ? }

? ? private void initEditText() {

? ? ? ? mEditText = new EditText(getContext());

? ? ? ? mEditText.addTextChangedListener(mTextWatcher);

? ? ? ? mEditText.setCursorVisible(false);

? ? ? ? ViewCompat.setBackground(mEditText, new ColorDrawable(Color.TRANSPARENT));

? ? ? ? mEditText.setTextColor(Color.TRANSPARENT);

? ? ? ? mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mCodeLength)});

? ? ? ? mEditText.setFocusable(true);

? ? ? ? mEditText.requestFocus();

? ? ? ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

? ? ? ? ? ? mEditText.setShowSoftInputOnFocus(true);

? ? ? ? }

? ? ? ? mEditText.setInputType(TYPE_CLASS_NUMBER);

? ? ? ? mEditText.setSingleLine();

? ? ? ? addView(mEditText, new LayoutParams(MATCH_PARENT, MATCH_PARENT));

? ? }

? ? /**

? ? * 是否顯示鍵盤(pán)

? ? *

? ? * @param showSystemKeyboard true為顯示,false為不顯示

? ? */

? ? public void setShowKeyboard(boolean showSystemKeyboard) {

? ? ? ? if (mShowSystemKeyboard == showSystemKeyboard) return;

? ? ? ? mShowSystemKeyboard = showSystemKeyboard;

? ? ? ? if (mShowSystemKeyboard) {

? ? ? ? ? ? mEditText.setInputType(TYPE_CLASS_NUMBER);

? ? ? ? } else {

? ? ? ? ? ? mEditText.setInputType(TYPE_NULL);

? ? ? ? }

? ? }

? ? public EditText getInputView() {

? ? ? ? return mEditText;

? ? }

? ? public void setText(CharSequence text) {

? ? ? ? if (mEditText != null) {

? ? ? ? ? ? mEditText.setText(text);

? ? ? ? }

? ? }

? ? private void initTextPaint() {

? ? ? ? mCodeTextPaint = new TextPaint();

? ? ? ? mCodeTextPaint.setColor(mCodeTextColor);

? ? ? ? mCodeTextPaint.setAntiAlias(true);

? ? ? ? mCodeTextPaint.setTextSize(mCodeTextSize);

? ? ? ? mCodeTextPaint.setFakeBoldText(true);

? ? ? ? mCodeTextPaint.setTextAlign(Paint.Align.CENTER);

? ? }

? ? private Drawable getFrameDrawable() {

? ? ? ? if (mFrameDrawableId == -1) {

? ? ? ? ? ? StateListDrawable drawable = new StateListDrawable();

? ? ? ? ? ? drawable.addState(STATE_NORMAL, ContextCompat.getDrawable(getContext(), mNormalId));

? ? ? ? ? ? drawable.addState(STATE_SELECTED, ContextCompat.getDrawable(getContext(), mSelectId));

? ? ? ? ? ? return drawable;

? ? ? ? } else {

? ? ? ? ? ? return ContextCompat.getDrawable(getContext(), mFrameDrawableId);

? ? ? ? }

? ? }

? ? private void initStateListDrawable() {

? ? ? ? for (int i = 0; i < mCodeLength; i++) {

? ? ? ? ? ? mInputDrawable.put(i, getFrameDrawable());

? ? ? ? }

? ? ? ? mCurIndex = mLastIndex = 0;

? ? ? ? setDrawableState(mCurIndex, STATE_SELECTED);

? ? }

//? ? private static boolean isAttrPxType(TypedArray typeArray, int index) {

//? ? ? ? return typeArray.peekValue(index).type == TypedValue.COMPLEX_UNIT_PX;

//? ? }

? ? public void setOnNumberInputListener(OnNumberInputListener listener) {

? ? ? ? this.mOnNumberInputListener = listener;

? ? }

? ? /**

? ? * 設(shè)置drawable state

? ? */

? ? private void setDrawableState(int index, int[] state) {

? ? ? ? if (index < 0 || index > mInputDrawable.size() - 1) return;

? ? ? ? mInputDrawable.get(index).setState(state);

? ? }

? ? @Override

? ? protected void onVisibilityChanged(@NonNull View changedView, int visibility) {

? ? ? ? super.onVisibilityChanged(changedView, visibility);

? ? ? ? if (getVisibility() != VISIBLE) {

? ? ? ? ? ? mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);

? ? ? ? }

? ? }

? ? @Override

? ? protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

? ? ? ? super.onMeasure(widthMeasureSpec, heightMeasureSpec);

? ? ? ? int width = MeasureSpec.getSize(widthMeasureSpec);

? ? ? ? int height = MeasureSpec.getSize(heightMeasureSpec);

? ? ? ? int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

? ? ? ? int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

? ? ? ? if (heightSpecMode == MeasureSpec.AT_MOST) {

? ? ? ? ? ? height = mFrameSize;

? ? ? ? }

? ? ? ? if (widthSpecMode != MeasureSpec.EXACTLY) {

? ? ? ? ? ? width = (mCodeLength * mFrameSize) + (mFramePadding * (mCodeLength - 1));

? ? ? ? }

? ? ? ? int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, width);

? ? ? ? int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, height);

? ? ? ? mEditText.measure(childWidthSpec, childHeightSpec);

? ? ? ? setMeasuredDimension(width, height);

? ? }

? ? public String getInputCode() {

? ? ? ? return mCodeText;

? ? }

? ? private String indexOfCode(int index) {

? ? ? ? if (TextUtils.isEmpty(mCodeText)) {

? ? ? ? ? ? return "";

? ? ? ? }

? ? ? ? if (index < 0 || index > mCodeText.length() - 1) {

? ? ? ? ? ? return "";

? ? ? ? }

? ? ? ? return String.valueOf(mCodeText.charAt(index));

? ? }

? ? @Override

? ? protected void onDraw(Canvas canvas) {

? ? ? ? super.onDraw(canvas);

? ? ? ? int left = 0;

? ? ? ? int right = mFrameSize;

? ? ? ? int size = mInputDrawable.size();

? ? ? ? for (int i = 0; i < size; i++) {

? ? ? ? ? ? Drawable drawable = mInputDrawable.get(i);

? ? ? ? ? ? drawable.setBounds(left, 0, right, getMeasuredHeight());

? ? ? ? ? ? drawable.draw(canvas);

? ? ? ? ? ? //繪制文本

? ? ? ? ? ? drawCodeText(canvas, drawable.getBounds(), indexOfCode(i));

? ? ? ? ? ? left = right + mFramePadding;

? ? ? ? ? ? right = left + mFrameSize;

? ? ? ? }

? ? }

? ? private void drawCodeText(Canvas canvas, Rect bound, String text) {

? ? ? ? if (!TextUtils.isEmpty(text)) {

? ? ? ? ? ? mCodeTextPaint.getTextBounds(text, 0, text.length(), mTextRect);

? ? ? ? ? ? canvas.drawText(text, bound.centerX(), bound.height() / 2 + mTextRect.height() / 2, mCodeTextPaint);

? ? ? ? }

? ? }

? ? public interface OnNumberInputListener {

? ? ? ? void onInputFinish();

? ? ? ? void onInputIng();

? ? }

}



?public interface OnNumberInputListener {

? ? ? ? void onInputFinish();

? ? ? ? void onInputIng();

}

該接口有兩個(gè)方法用來(lái)監(jiān)聽(tīng)輸入完成、正在輸入



像素轉(zhuǎn)換工具類(lèi):PixelUtil

/**

* 像素轉(zhuǎn)換工具類(lèi)

*/

public class PixelUtil {

? ? /**

? ? * The context.

? ? */

? ? private Context context;

? ? public PixelUtil(Context context) {

? ? ? ? this.context = context;

? ? }

? ? public static boolean isPxVal(TypedValue val) {

? ? ? ? if (val != null && val.type == TypedValue.TYPE_DIMENSION &&

? ? ? ? ? ? ? ? getComplexUnit(val.data) == TypedValue.COMPLEX_UNIT_PX) {

? ? ? ? ? ? return true;

? ? ? ? }

? ? ? ? return false;

? ? }

? ? private static int getComplexUnit(int data) {

? ? ? ? return TypedValue.COMPLEX_UNIT_MASK & (data >> TypedValue.COMPLEX_UNIT_SHIFT);

? ? }

? ? /**

? ? * dp? px.

? ? *

? ? * @param value the value

? ? * @return the int

? ? */

? ? public int dp2px(float value) {

? ? ? ? final float density = context.getResources().getDisplayMetrics().density;

? ? ? ? return (int) (value * density + 0.5f);

? ? }

? ? /**

? ? * px?dp.

? ? *

? ? * @param value the value

? ? * @return the int

? ? */

? ? public int px2dp(float value) {

? ? ? ? final float scale = context.getResources().getDisplayMetrics().densityDpi;

? ? ? ? return (int) ((value * 160) / scale + 0.5f);

? ? }

? ? /**

? ? * sp?px.

? ? *

? ? * @param value the value

? ? * @return the int

? ? */

? ? public int sp2px(float value) {

? ? ? ? Resources r;

? ? ? ? if (context == null) {

? ? ? ? ? ? r = Resources.getSystem();

? ? ? ? } else {

? ? ? ? ? ? r = context.getResources();

? ? ? ? }

? ? ? ? float spvalue = value * r.getDisplayMetrics().scaledDensity;

? ? ? ? return (int) (spvalue + 0.5f);

? ? }

? ? /**

? ? * px?sp.

? ? *

? ? * @param value the value

? ? * @return the int

? ? */

? ? public int px2sp(float value) {

? ? ? ? final float scale = context.getResources().getDisplayMetrics().scaledDensity;

? ? ? ? return (int) (value / scale + 0.5f);

? ? }

? ? public int width() {

? ? ? ? return context.getResources().getDisplayMetrics().widthPixels;

? ? }

? ? public int height() {

? ? ? ? return context.getResources().getDisplayMetrics().heightPixels;

? ? }

}



attrs.xml

<?xml version="1.0" encoding="utf-8"?>

<resources>

? ? <declare-styleable name="NumberCodeView">

? ? ? ? <attr name="codeTextColor" format="color|reference" />

? ? ? ? <attr name="codeTextSize" format="reference|dimension" />

? ? ? ? <attr name="frameSize" format="reference|dimension" />

? ? ? ? <attr name="framePadding" format="reference|dimension" />

? ? ? ? <attr name="codeLength" format="integer|reference" />

? ? ? ? <attr name="frameDrawableId" format="reference" />

? ? ? ? <attr name="normal" format="reference" />

? ? ? ? <attr name="select" format="reference" />

? ? </declare-styleable>

</resources>



完整代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坑匠,一起剝皮案震驚了整個(gè)濱河市血崭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖夹纫,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咽瓷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡舰讹,警方通過(guò)查閱死者的電腦和手機(jī)茅姜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)月匣,“玉大人钻洒,你說(shuō)我怎么就攤上這事〕” “怎么了素标?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萍悴。 經(jīng)常有香客問(wèn)我头遭,道長(zhǎng),這世上最難降的妖魔是什么癣诱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任计维,我火速辦了婚禮,結(jié)果婚禮上狡刘,老公的妹妹穿的比我還像新娘享潜。我一直安慰自己,他們只是感情好嗅蔬,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著疾就,像睡著了一般澜术。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猬腰,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天鸟废,我揣著相機(jī)與錄音,去河邊找鬼姑荷。 笑死盒延,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鼠冕。 我是一名探鬼主播添寺,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懈费!你這毒婦竟也來(lái)了计露?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎票罐,沒(méi)想到半個(gè)月后叉趣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡该押,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年疗杉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚕礼。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烟具,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闻牡,到底是詐尸還是另有隱情净赴,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布罩润,位于F島的核電站玖翅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏割以。R本人自食惡果不足惜金度,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望严沥。 院中可真熱鬧猜极,春花似錦、人聲如沸消玄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)翩瓜。三九已至受扳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間兔跌,已是汗流浹背勘高。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坟桅,地道東北人华望。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像仅乓,于是被迫代替她去往敵國(guó)和親赖舟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容