安卓不同機型和API版本中拍照和相冊選取照片功能實現(xiàn)

該demo針對不同機型和不同API進行功能實現(xiàn)属铁,滿足大部分手機拍照和相冊選取照片功能實現(xiàn)择膝。
1使用知乎相冊框架compile 'com.zhihu.android:matisse:0.4.3'進行圖庫相冊選取
2使用compile 'com.github.bumptech.glide:glide:3.7.0'框架(Glide)進行圖片加載


如下效果

1點擊選擇圖片按鈕彈出popuwindow


01.png

2拍照:


02.png

3相冊選取:


03.png

4選擇的結果:
04.png

SelectPicPopup的代碼:

package study.lzl.photoselectdemo;

import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.PopupWindow;

/**
 * @author: Created by lzl on 2017/8/14.
 * @function:
 * @description:
 */

public class SelectPicPopup implements View.OnClickListener {
    /**
     * UI
     */
    private PopupWindow mPopupWindow;
    private Button mCameraBtn;//相冊
    private Button mPicBtn;//圖庫
    private Button mCancelBtn;//取消
    private Context mContext;//上下文環(huán)境對象

    private OnBtnClickListener click;

    public PopupWindow getmPopupWindow() {
        return mPopupWindow;
    }

    /**
     * 單參構造
     * @param mContext
     */
    public SelectPicPopup(Context mContext) {
        this.mContext = mContext;
        mPopupWindow=new PopupWindow(mContext);
        mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
        mPopupWindow.setWidth(WindowManager.LayoutParams.MATCH_PARENT);//寬度充滿父窗體
        mPopupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);//高度包裹內(nèi)容
        mPopupWindow.setTouchable(true);//設置可以被觸摸
        mPopupWindow.setFocusable(true);//設置占據(jù)焦點
        mPopupWindow.setOutsideTouchable(true);//設置可以點擊外部區(qū)域(點擊外部區(qū)域?qū)⑾?
        mPopupWindow.setContentView(initView());
        mPopupWindow.setAnimationStyle(R.style.AnimBottom);//設置轉場動畫
        mPopupWindow.getContentView().setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                mPopupWindow.setFocusable(false);
                dismiss();
                return false;
            }
        });
    }

    private View initView() {
        View view= LayoutInflater.from(mContext).inflate(R.layout.layout_popup,null);
        mCameraBtn= (Button) view.findViewById(R.id.camera_btn);
        mCameraBtn.setOnClickListener(this);

        mPicBtn= (Button) view.findViewById(R.id.pic_btn);
        mPicBtn.setOnClickListener(this);
        mCancelBtn= (Button) view.findViewById(R.id.cancel_btn);
        mCancelBtn.setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.camera_btn:
                click.getFlag(0);
                break;
            case R.id.pic_btn:
                click.getFlag(1);
                break;
            case R.id.cancel_btn:
                dismiss();
                break;
        }
    }

    protected void dismiss(){
        if (mPopupWindow!=null&&mPopupWindow.isShowing()){
            mPopupWindow.dismiss();
        }
    }

    /**
     *
     * @param rootView
     */
    protected void showPopup(View rootView){
        mPopupWindow.showAtLocation(rootView, Gravity.BOTTOM,0,0);
    }

    protected interface OnBtnClickListener{
        void getFlag(int flag);
    }

    protected void setOnBtnClick(OnBtnClickListener click){
        this.click=click;
    }
}

自定義的popuwindow使用的style如下:

<!--popuwindow style-->
    <style name="AnimBottom" parent="@android:style/Animation">
        <item name="android:windowEnterAnimation">@anim/popup_alpha_out</item>
        <item name="android:windowExitAnimation">@anim/popup_alpha_in</item>
    </style>

引用的兩個anim文件:
1anim/popup_alpha_out:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    >

</alpha>

2anim/popup_alpha_in:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="1.0"
    android:toAlpha="0.0"
    >

</alpha>

布局文件:layout_popup.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/half_transparent_black">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:background="@color/page_bg_color">
        <Button
            android:id="@+id/camera_btn"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="#ffffff"
            android:text="拍照"
            android:textColor="#000"
            />
        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="#65000000"/>
        <Button
            android:id="@+id/pic_btn"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="相冊"
            android:textColor="#000"
            android:background="#ffffff"/>
        <Button
            android:id="@+id/cancel_btn"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginTop="10dp"
            android:background="#ffffffff"
            android:textColor="#000"
            android:text="取消"/>
    </LinearLayout>
</RelativeLayout>

MainActivity的代碼:

package study.lzl.photoselectdemo;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.zhihu.matisse.Matisse;
import com.zhihu.matisse.MimeType;
import com.zhihu.matisse.engine.impl.GlideEngine;

import java.io.File;
import java.util.List;

/**
 * 演示圖片選擇來源昨凡,并將圖片正確顯示在控件上导街,該控件可以對圖片進行手勢操作:包括大小縮放和平移拖拽
 */
public class MainActivity extends AppCompatActivity {
    private ImageView imageV;
    private Uri imageUrl;//照片地址uri對象
    private int destType = FileHelper.JPEG;
    private static final int REQUEST_CODE_TAKE_PIC_CAMERA = 100;//拍照請求碼

    private static final int REQUEST_CODE_CHOOSE = 233;//圖庫選取照片請求碼

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        imageV= (ImageView) findViewById(R.id.image);
        findViewById(R.id.select_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final SelectPicPopup popup=new SelectPicPopup(getApplicationContext());
                popup.showPopup(findViewById(R.id.activity_main));
                popup.setOnBtnClick(new SelectPicPopup.OnBtnClickListener() {
                    @Override
                    public void getFlag(int flag) {
                        if (flag==1){//相冊
                            popup.dismiss();
                            selectPicFromGallery();
                        }else if (flag==0){//拍照
                            popup.dismiss();
                            if (hasPermission(PerMissionContants.HARDWEAR_CAMERA_PERMISSION)){
                                openCamera();
                            }else {
                                requestPermission(PerMissionContants.HARDWEAR_CAMERA_CODE,PerMissionContants.HARDWEAR_CAMERA_PERMISSION);
                                Toast.makeText(getApplicationContext(),"權限:"+hasPermission(PerMissionContants.HARDWEAR_CAMERA_PERMISSION),Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                });
            }
        });
    }

    /**
     * 打開相冊進行拍照
     */
    private void openCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //創(chuàng)建一個臨時文件夾存儲拍攝的照片
        File file = FileHelper.createFileByType(getApplicationContext(), destType, System.currentTimeMillis()+"");
        imageUrl=Uri.fromFile(file);//解析出uri對象
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//版本過高的拍照路徑
            Log.e("進入1","進入1");
            file = new File(getApplicationContext().getCacheDir(), System.currentTimeMillis()+".jpg");
            imageUrl = Uri.fromFile(file);

            Toast.makeText(getApplicationContext(), "TODO", Toast.LENGTH_SHORT).show();
            // 將文件轉換成content://Uri的形式
            Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", file);
            // 申請臨時訪問權限
            takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);

        } else {
            Log.e("進入2","進入2");
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUrl);
        }


        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            Log.e("進入3","進入3");
            startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PIC_CAMERA);
        }
    }

    /**
     * 打開相冊選取照片
     */
    private void selectPicFromGallery() {
        Matisse.from(MainActivity.this)
                .choose(MimeType.allOf())
                .countable(true)
                .spanCount(4)
                .maxSelectable(1)
                .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                .thumbnailScale(0.85f)
                .imageEngine(new GlideEngine())
                .forResult(REQUEST_CODE_CHOOSE);
    }

    /**
     * 發(fā)起權限請求
     */
    private void requestPermission(int code,String...permissions){
        if (Build.VERSION.SDK_INT>=23){//判斷是否大于6.0版本(當前手機的安卓系統(tǒng)是否是6.0或以上)
            requestPermissions(permissions,code);
        }
    }

    /**
     * 校驗權限是否通過(安卓6.0以上的動態(tài)權限需要調(diào)用該方法)
     * @param permissions
     * @return
     */
    private boolean hasPermission(String...permissions){
        for (String permission:permissions) {
            if (ContextCompat.checkSelfPermission(getApplicationContext(),permission)!= PackageManager.PERMISSION_GRANTED){
                return false;
            }
        }
        return true;
    }

    /**
     * 權限請求回調(diào)結果處理
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode==PerMissionContants.HARDWEAR_CAMERA_CODE){//拍照權限
            if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                Toast.makeText(getApplicationContext(),"權限請求結果",Toast.LENGTH_SHORT).show();
                openCamera();
            }

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode==REQUEST_CODE_TAKE_PIC_CAMERA&&resultCode==RESULT_OK){//拍照請求回調(diào)成功
            if (imageUrl!=null){
                //根據(jù)uri獲取圖片的真實路徑
                String path=getRealFilePath(getApplicationContext(),imageUrl);
                Bitmap bitmap=BitmapFactory.decodeFile(path);//根據(jù)圖片的路徑字符串解析成bitmap
                imageV.setImageBitmap(bitmap);
            }
        }else if (requestCode==REQUEST_CODE_CHOOSE&&resultCode==RESULT_OK){
            List<Uri> uriList=Matisse.obtainResult(data);
            if (uriList.size()==1){
                String path=getRealFilePath(getApplicationContext(),uriList.get(0));
                Bitmap bitmap=BitmapFactory.decodeFile(path);//根據(jù)圖片的路徑字符串解析成bitmap
                imageV.setImageBitmap(bitmap);
            }
        }
    }

    /**
     * 該方法根據(jù)圖片uri得出其真實路徑
     * @param context 上下文
     * @param uri 圖片對應的uri對象
     * @return 圖片的真實路徑字符串
     */
    public String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) return null;
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }
}

布局文件:activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="study.lzl.photoselectdemo.MainActivity">

    <Button
        android:id="@+id/select_btn"
        android:background="@color/colorAccent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="選擇照片"
        android:textColor="@color/colorPrimary"/>

    <ImageView
        android:id="@+id/image"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"/>

</RelativeLayout>


動態(tài)權限常量類:PerMissionContants

package study.lzl.photoselectdemo;

import android.Manifest;

/**
 * @author: Created by lzl on 2017/8/15.
 * @function:
 * @description:
 */

public class PerMissionContants {
    /**
     * 拍照權限碼
     */
    public static final int HARDWEAR_CAMERA_CODE=0x01;
    /**
     * 拍照用到的權限字符串數(shù)組:1打開數(shù)組的權限  2文件的寫入權限(拍照要緩存) 3所拍照片的獲瘸苌摺(從本地緩存或者相冊中獲瓤源印)
     */
    public static final String[] HARDWEAR_CAMERA_PERMISSION=new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE};
}


文件操作助手類:FileHelper

package study.lzl.photoselectdemo;

import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.text.TextUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by rookie on 2017/2/28.
 */

public class FileHelper {
    public static final int JPEG = 1;
    static final int PNG = 0;


    /**
     * 返回系統(tǒng)緩存路徑
     *
     * @param mContext
     * @return
     */
    public static String getTempDirectoryPath(Context mContext) {
        File cachePath;
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            cachePath = mContext.getExternalCacheDir();
        } else {
            cachePath = mContext.getCacheDir();
        }
        cachePath.mkdirs();
        return cachePath.getAbsolutePath();
    }

    /**
     * 在系統(tǒng)緩存中創(chuàng)建一個文件
     *
     * @param mContext
     * @param type
     * @param name
     * @return
     */
    public static File createFileByType(Context mContext, int type, String name) {
        if (TextUtils.isEmpty(name)) {
            name = ".pic";
        }

        switch (type) {
            case JPEG:
                name = name + ".jpg";
                break;
            case PNG:
                name = name + ".png";
                break;
            default:
                break;

        }
        return new File(getTempDirectoryPath(mContext), name);

    }

    /**
     * Removes the "file://" prefix from the given URI string, if applicable.
     * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
     *
     * @param uriString the URI string to operate on
     * @return a path without the "file://" prefix
     */
    public static String stripFileProtocol(String uriString) {
        if (uriString.startsWith("file://")) {
            uriString = uriString.substring(7);
        }
        return uriString;
    }

    public static String getPicutresPath(int encodingType) {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "IMG_" + timeStamp + (encodingType == JPEG ? ".jpg" : ".png");
        File storageDir = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DCIM);
        String galleryPath = storageDir.getAbsolutePath() + File.separator + "Camera" + File.separator + imageFileName;
        return galleryPath;
    }

    public static boolean copyResultToGalley(Context context, Uri originUri, Uri galleryUri) {
        boolean result = false;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            inputStream = context.getContentResolver().openInputStream(originUri);
            outputStream = context.getContentResolver().openOutputStream(galleryUri);

            byte[] buffer = new byte[2048];

            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
            result = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
}

***

注意事項:
1在app.gradle配置文件中配置使用到的兩個框架:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'
    //項目中需要用到的第三方框架
    compile 'com.zhihu.android:matisse:0.4.3'
    compile 'com.github.bumptech.glide:glide:3.7.0'
}

2安卓6.0以上版本使用的是動態(tài)權限管理:因此增加一個類進行權限的申請?zhí)幚?PerMissionContants

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末朝蜘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涩金,更是在濱河造成了極大的恐慌谱醇,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件步做,死亡現(xiàn)場離奇詭異副渴,居然都是意外死亡,警方通過查閱死者的電腦和手機全度,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門煮剧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事勉盅∮悠模” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵草娜,是天一觀的道長挑胸。 經(jīng)常有香客問我,道長宰闰,這世上最難降的妖魔是什么茬贵? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮议蟆,結果婚禮上闷沥,老公的妹妹穿的比我還像新娘。我一直安慰自己咐容,他們只是感情好舆逃,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戳粒,像睡著了一般路狮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蔚约,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天奄妨,我揣著相機與錄音,去河邊找鬼苹祟。 笑死砸抛,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的树枫。 我是一名探鬼主播直焙,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砂轻!你這毒婦竟也來了奔誓?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤搔涝,失蹤者是張志新(化名)和其女友劉穎厨喂,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庄呈,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕煌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了诬留。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幌绍。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡颁褂,死狀恐怖故响,靈堂內(nèi)的尸體忽然破棺而出傀广,到底是詐尸還是另有隱情,我是刑警寧澤彩届,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布伪冰,位于F島的核電站,受9級特大地震影響樟蠕,放射性物質(zhì)發(fā)生泄漏贮聂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一寨辩、第九天 我趴在偏房一處隱蔽的房頂上張望吓懈。 院中可真熱鬧,春花似錦靡狞、人聲如沸耻警。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甘穿。三九已至,卻和暖如春梢杭,著一層夾襖步出監(jiān)牢的瞬間温兼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工武契, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留募判,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓咒唆,卻偏偏與公主長得像届垫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钧排,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,327評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理敦腔,服務發(fā)現(xiàn),斷路器恨溜,智...
    卡卡羅2017閱讀 134,716評論 18 139
  • 一.榜單介紹 排行榜包括四大類: 單一框架:僅提供路由符衔、網(wǎng)絡層、UI層糟袁、通信層或其他單一功能的框架 混合開發(fā)框架:...
    偉子男閱讀 5,244評論 0 161
  • 金融理財產(chǎn)品的銷售渠道合集: 首先判族,給我們的客戶定位,以ABCD類來定位客戶: A類:有錢有意向 B類:有錢無意向...
    畫與話閱讀 1,276評論 1 0
  • 一個電商產(chǎn)品設計中圖片占據(jù)80%项戴,所以圖片的質(zhì)量對整體設計品質(zhì)有直接影響形帮。 上圖中左邊的界面比右邊的界面更舒適、更...
    fcfdesign閱讀 341評論 0 0