Android登陸頁面仿拉鉤動(dòng)效,你總會(huì)需要它!

哈哈,看到這個(gè)標(biāo)題是不是JH一緊,你可能會(huì)說我就沒遇到過,但是現(xiàn)在沒遇到不代表就遇不到,畢竟設(shè)計(jì)也是變幻莫測,只有你想不到的,沒有你不能實(shí)現(xiàn)的,說的這么吊,到底是啥效果?沒錯(cuò)就是一個(gè)小小的登錄頁面,大家都有拉勾app吧,看拉勾的登錄頁做的很是平滑動(dòng)畫,而且?guī)?dòng)畫效果,所以就有了類似拉勾登錄效果,如圖:

登錄動(dòng)畫

github地址
雖然是個(gè)簡單的頁面,但是涵蓋的東西不算少啊,很納悶為何谷歌一直不提供簡單,方便,準(zhǔn)確的鍵盤監(jiān)聽事件?惆悵啊,所以我們只能自己從側(cè)面監(jiān)聽鍵盤事件了,我們可以監(jiān)聽最外層布局的變化來判斷鍵盤是不是彈起了。閑話不多說,上車吧。
布局文件,大家都能看懂吧。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:clipToPadding="true"
    android:background="@color/color_ffffff"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/logo"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:background="@null"
        android:layout_marginTop="80dp"
        android:scaleType="centerCrop"
        android:src="@drawable/skin_about_brand" />

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:fillViewport="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:scrollbarThumbVertical="@android:color/transparent"
        android:scrollbars="vertical"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

        <LinearLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:orientation="vertical"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="55dp"
                android:layout_marginTop="200dp"
                android:gravity="center_vertical"
                android:orientation="horizontal"
                android:paddingLeft="13dp">

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="15dp"
                    android:src="@drawable/ic_mobile_flag" />

                <EditText
                    android:id="@+id/et_mobile"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@null"
                    android:hint="@string/hint_login_username"
                    android:inputType="textVisiblePassword"
                    android:maxLength="11"
                    android:singleLine="true"
                    android:text=""
                    android:textColor="@color/color_999999"
                    android:textColorHint="@color/color_999999"
                    android:textSize="14dp" />

                <ImageView
                    android:id="@+id/iv_clean_phone"
                    android:layout_width="40dp"
                    android:layout_height="fill_parent"
                    android:scaleType="centerInside"
                    android:src="@drawable/ic_clear"
                    android:visibility="gone" />
            </LinearLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@color/color_eeeeee" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="55dp"
                android:gravity="center_vertical"
                android:orientation="horizontal"
                android:paddingLeft="13dp">

                <ImageView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginRight="15dp"
                    android:src="@drawable/ic_password_flag" />

                <EditText
                    android:id="@+id/et_password"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="1"
                    android:background="@null"
                    android:hint="@string/hint_login_password"
                    android:inputType="textPassword"
                    android:maxLength="30"
                    android:singleLine="true"
                    android:text=""
                    android:textColor="@color/color_999999"
                    android:textColorHint="@color/color_999999"
                    android:textSize="14dp" />

                <ImageView
                    android:id="@+id/clean_password"
                    android:layout_width="40dp"
                    android:layout_height="fill_parent"
                    android:scaleType="centerInside"
                    android:src="@drawable/ic_clear"
                    android:visibility="gone" />

                <ImageView
                    android:id="@+id/iv_show_pwd"
                    android:layout_width="40dp"
                    android:layout_height="fill_parent"
                    android:scaleType="centerInside"
                    android:src="@drawable/pass_gone" />
            </LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:background="@color/color_eeeeee" />

            <Button
                android:id="@+id/btn_login"
                android:layout_width="match_parent"
                android:layout_height="45dp"
                android:layout_marginBottom="10dp"
                android:layout_marginTop="21dp"
                android:background="@drawable/bg_btn_login_selected"
                android:text="@string/login"
                android:textColor="@color/color_ffffff"
                android:textSize="18dp" />
            <LinearLayout
                android:layout_width="match_parent"
                android:orientation="horizontal"
                android:layout_height="wrap_content">
                <TextView
                    android:id="@+id/regist"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right"
                    android:layout_marginBottom="10dp"
                    android:text="注冊(cè)新用戶"
                    android:layout_weight="1"
                    android:textColor="@color/color_b0b8b2"
                    android:textSize="14dp" />
                <TextView
                    android:id="@+id/forget_password"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="right"
                    android:layout_marginBottom="10dp"
                    android:layout_marginLeft="21dp"
                    android:text="@string/login_forget_pwd"
                    android:textColor="@color/color_b0b8b2"
                    android:textSize="14dp" />
            </LinearLayout>

        </LinearLayout>

    </ScrollView>

    <LinearLayout
        android:id="@+id/service"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:gravity="center"
        android:padding="10dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_height="wrap_content">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="聯(lián)系客服"
            android:textColor="@color/color_b0b8b2"
            android:textSize="14dp" />
        <View
            android:layout_width="1dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:background="@color/color_eeeeee"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="關(guān)于我們"
            android:textColor="@color/color_b0b8b2"
            android:textSize="14dp" />
    </LinearLayout>

</RelativeLayout>

我們要想監(jiān)聽鍵盤事件,首先我們想得到的是鍵盤彈起的時(shí)候我們可以去搞點(diǎn)事情,鍵盤搜起的時(shí)候我們?cè)偃ジ泓c(diǎn)事情,知道這些還不夠,我們還要知道鍵盤彈起了多少,以及需要平移多少的距離。我們都知道我們的一個(gè)頁面彈起鍵盤的時(shí)候這個(gè)頁面的根布局會(huì)回調(diào)他的監(jiān)聽方法:addOnLayoutChangeListener( );當(dāng)鍵盤彈起的時(shí)候,我們的布局是變化了,因此會(huì)執(zhí)行這個(gè)回調(diào)方法,但是前提是必須設(shè)置我們的Activity的windowSoftInputMode屬性為adjustResize。

我們想讓布局整體平移的距離也就是彈起時(shí)候處于最底部的view距離頂部的高度減去我們鍵盤的高度。現(xiàn)在認(rèn)為只要控件將Activity向上推的高度超過了1/3屏幕高,就認(rèn)為軟鍵盤彈起

scrollView.addOnLayoutChangeListener(new ViewGroup.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
              /* old是改變前的左上右下坐標(biāo)點(diǎn)值,沒有old的是改變后的左上右下坐標(biāo)點(diǎn)值
              現(xiàn)在認(rèn)為只要控件將Activity向上推的高度超過了1/3屏幕高,就認(rèn)為軟鍵盤彈起*/
                if (oldBottom != 0 && bottom != 0 && (oldBottom - bottom > keyHeight)) {
                    Log.e("wenzhihao", "up------>"+(oldBottom - bottom));
                    int dist = btn_login.getBottom() - bottom;
                    if (dist>0){
                        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", 0.0f, -dist);
                        mAnimatorTranslateY.setDuration(300);
                        mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
                        mAnimatorTranslateY.start();
                        zoomIn(logo, dist);
                    }
                    service.setVisibility(View.INVISIBLE);

                } else if (oldBottom != 0 && bottom != 0 && (bottom - oldBottom > keyHeight)) {
                    Log.e("wenzhihao", "down------>"+(bottom - oldBottom));
                    if ((btn_login.getBottom() - oldBottom)>0){
                        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", content.getTranslationY(), 0);
                        mAnimatorTranslateY.setDuration(300);
                        mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
                        mAnimatorTranslateY.start();
                        //鍵盤收回后,logo恢復(fù)原來大小,位置同樣回到初始位置
                        zoomOut(logo);
                    }
                    service.setVisibility(View.VISIBLE);
                }
            }
        });
//btn_login是登錄按鈕

這樣我們發(fā)現(xiàn)是可以實(shí)現(xiàn)效果了,但是我想全屏顯示,懵比了,發(fā)現(xiàn)全屏的時(shí)候不回調(diào)這個(gè)方法了,怎么辦?又是查資料一看原來這個(gè)也是一個(gè)bug,但是有解決方案,AndroidBug5497Workaround。也是谷歌提供的?直接拷貝過來,會(huì)發(fā)現(xiàn)其實(shí)他的作用就是讓Activity最外層的根布局,當(dāng)有布局變化時(shí)去響應(yīng)這個(gè)變化mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener();

package com.wzh.study.login;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;

public class AndroidBug5497Workaround {

    // For more information, see https://code.google.com/p/android/issues/detail?id=5497
    // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

    public static void assistActivity (Activity activity) {
        new AndroidBug5497Workaround(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    }

}

使用方式,如果我們?cè)O(shè)置了全屏,就去加載它,不設(shè)置不管:

if(isFullScreen(this)){
            AndroidBug5497Workaround.assistActivity(this);
}
...
public boolean isFullScreen(Activity activity) {
    return (activity.getWindow().getAttributes().flags &
            WindowManager.LayoutParams.FLAG_FULLSCREEN)==WindowManager.LayoutParams.FLAG_FULLSCREEN;
}

接下來就看具體動(dòng)畫事件了,鍵盤彈起來的時(shí)候整體向上平移,LOGO縮小,鍵盤收起的時(shí)候整體下移,并且LOGO恢復(fù)原來大小。這里用到的都是屬性動(dòng)畫,只有屬性動(dòng)畫我們才可以實(shí)現(xiàn)真正平移效果。

我看網(wǎng)上很多人使用addOnLayoutChangeListener()去監(jiān)聽鍵盤事件,但是這個(gè)方法回調(diào)的太頻繁,比如本例特效,輸入框后面有文字時(shí)候顯示清除的圖標(biāo),如果用這個(gè)方法那么也會(huì)執(zhí)行一次,可能會(huì)影響你的動(dòng)畫,當(dāng)然你也可以去記錄第一次的高度讓他不會(huì)走邏輯,但是我覺得也不是很靠譜,雖然我這個(gè)方法也不是很棒 ?乛?乛?~。

最后貼上源碼:

package com.wzh.study.login;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.wzh.study.R;

/**
 * Created by WZH on 2017/3/25.
 */

public class OtherLoginAct  extends FragmentActivity implements View.OnClickListener  {
    private ImageView logo;
    private ScrollView scrollView;
    private EditText et_mobile;
    private EditText et_password;
    private ImageView iv_clean_phone;
    private ImageView clean_password;
    private ImageView iv_show_pwd;
    private Button btn_login;
    private TextView forget_password;

    private int screenHeight = 0;//屏幕高度
    private int keyHeight = 0; //軟件盤彈起后所占高度
    private float scale = 0.6f; //logo縮放比例
    private View service,content;
    private int height = 0 ;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other_login);
        if(isFullScreen(this)){
            AndroidBug5497Workaround.assistActivity(this);
        }
        initView();
        initListener();
    }
    public boolean isFullScreen(Activity activity) {
        return (activity.getWindow().getAttributes().flags &
                WindowManager.LayoutParams.FLAG_FULLSCREEN)==WindowManager.LayoutParams.FLAG_FULLSCREEN;
    }
    private void initView() {
        logo = (ImageView) findViewById(R.id.logo);
        scrollView = (ScrollView) findViewById(R.id.scrollView);
        et_mobile = (EditText) findViewById(R.id.et_mobile);
        et_password = (EditText) findViewById(R.id.et_password);
        iv_clean_phone = (ImageView) findViewById(R.id.iv_clean_phone);
        clean_password = (ImageView) findViewById(R.id.clean_password);
        iv_show_pwd = (ImageView) findViewById(R.id.iv_show_pwd);
        btn_login = (Button) findViewById(R.id.btn_login);
        forget_password = (TextView) findViewById(R.id.forget_password);
        service = findViewById(R.id.service);
        content = findViewById(R.id.content);
        screenHeight = this.getResources().getDisplayMetrics().heightPixels; //獲取屏幕高度
        keyHeight = screenHeight / 3;//彈起高度為屏幕高度的1/3
    }
    private void initListener() {
        iv_clean_phone.setOnClickListener(this);
        clean_password.setOnClickListener(this);
        iv_show_pwd.setOnClickListener(this);
        et_mobile.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) {
                if (!TextUtils.isEmpty(s) && iv_clean_phone.getVisibility() == View.GONE) {
                    iv_clean_phone.setVisibility(View.VISIBLE);
                } else if (TextUtils.isEmpty(s)) {
                    iv_clean_phone.setVisibility(View.GONE);
                }
            }
        });
        et_password.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) {
                if (!TextUtils.isEmpty(s) && clean_password.getVisibility() == View.GONE) {
                    clean_password.setVisibility(View.VISIBLE);
                } else if (TextUtils.isEmpty(s)) {
                    clean_password.setVisibility(View.GONE);
                }
                if (s.toString().isEmpty())
                    return;
                if (!s.toString().matches("[A-Za-z0-9]+")) {
                    String temp = s.toString();
                    Toast.makeText(OtherLoginAct.this, R.string.please_input_limit_pwd, Toast.LENGTH_SHORT).show();
                    s.delete(temp.length() - 1, temp.length());
                    et_password.setSelection(s.length());
                }
            }
        });
        /**
         * 禁止鍵盤彈起的時(shí)候可以滾動(dòng)
         */
        scrollView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });
        scrollView.addOnLayoutChangeListener(new ViewGroup.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
              /* old是改變前的左上右下坐標(biāo)點(diǎn)值,沒有old的是改變后的左上右下坐標(biāo)點(diǎn)值
              現(xiàn)在認(rèn)為只要控件將Activity向上推的高度超過了1/3屏幕高,就認(rèn)為軟鍵盤彈起*/
                if (oldBottom != 0 && bottom != 0 && (oldBottom - bottom > keyHeight)) {
                    Log.e("wenzhihao", "up------>"+(oldBottom - bottom));
                    int dist = content.getBottom() - bottom;
                    if (dist>0){
                        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", 0.0f, -dist);
                        mAnimatorTranslateY.setDuration(300);
                        mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
                        mAnimatorTranslateY.start();
                        zoomIn(logo, dist);
                    }
                    service.setVisibility(View.INVISIBLE);

                } else if (oldBottom != 0 && bottom != 0 && (bottom - oldBottom > keyHeight)) {
                    Log.e("wenzhihao", "down------>"+(bottom - oldBottom));
                    if ((content.getBottom() - oldBottom)>0){
                        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(content, "translationY", content.getTranslationY(), 0);
                        mAnimatorTranslateY.setDuration(300);
                        mAnimatorTranslateY.setInterpolator(new LinearInterpolator());
                        mAnimatorTranslateY.start();
                        //鍵盤收回后,logo恢復(fù)原來大小,位置同樣回到初始位置
                        zoomOut(logo);
                    }
                    service.setVisibility(View.VISIBLE);
                }
            }
        });
    }
    /**
     * 縮小
     * @param view
     */
    public void zoomIn(final View view, float dist) {
        view.setPivotY(view.getHeight());
        view.setPivotX(view.getWidth() / 2);
        AnimatorSet mAnimatorSet = new AnimatorSet();
        ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, scale);
        ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, scale);
        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(view, "translationY", 0.0f, -dist);

        mAnimatorSet.play(mAnimatorTranslateY).with(mAnimatorScaleX);
        mAnimatorSet.play(mAnimatorScaleX).with(mAnimatorScaleY);
        mAnimatorSet.setDuration(300);
        mAnimatorSet.start();
    }

    /**
     * f放大
     * @param view
     */
    public void zoomOut(final View view) {
        view.setPivotY(view.getHeight());
        view.setPivotX(view.getWidth() / 2);
        AnimatorSet mAnimatorSet = new AnimatorSet();

        ObjectAnimator mAnimatorScaleX = ObjectAnimator.ofFloat(view, "scaleX", scale, 1.0f);
        ObjectAnimator mAnimatorScaleY = ObjectAnimator.ofFloat(view, "scaleY", scale, 1.0f);
        ObjectAnimator mAnimatorTranslateY = ObjectAnimator.ofFloat(view, "translationY", view.getTranslationY(), 0);

        mAnimatorSet.play(mAnimatorTranslateY).with(mAnimatorScaleX);
        mAnimatorSet.play(mAnimatorScaleX).with(mAnimatorScaleY);
        mAnimatorSet.setDuration(300);
        mAnimatorSet.start();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.iv_clean_phone:
                et_mobile.setText("");
                break;
            case R.id.clean_password:
                et_password.setText("");
                break;
            case R.id.iv_show_pwd:
                if (et_password.getInputType() != InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) {
                    et_password.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
                    iv_show_pwd.setImageResource(R.drawable.pass_visuable);
                } else {
                    et_password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                    iv_show_pwd.setImageResource(R.drawable.pass_gone);
                }
                String pwd = et_password.getText().toString();
                if (!TextUtils.isEmpty(pwd))
                    et_password.setSelection(pwd.length());
                break;
        }
    }
}


如果有什么問題歡迎指出,我將給出例子地址,包含另一種實(shí)現(xiàn)方式就是用scrollview滑動(dòng)到最底部的方式來實(shí)現(xiàn)平移效果~
github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容