Launcher3 5.1 客制化定制问题修改(更新7.0MTK和高通的修改)

本文全部是基于将双层界面修改成单层桌面的问题

最近客户提出要客制化定制Launcher3
对最近的修改做个笔记

1.修改默认壁纸

替换 frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.jpg即可(注意找到对应的分辨率)

2.将双层桌面改成单层桌面

LauncherAppState.java

    public static boolean isDisableAllApps() {
      ...
      return true 即可
    }

3.删除谷歌搜索

Launcher.java

 public View getQsbBar() {
  ...
   return null; 即可
  }

注意上面会隐藏谷歌搜索,但是还会占着位置
想要不占位置
DeviceProfile.java

private void updateIconSize(float scale, int drawablePadding, Resources resources,
                                DisplayMetrics dm) {      
   ...   
     // Search Bar
  ...
        searchBarSpaceHeightPx = getSearchBarTopOffset()
                + resources.getDimensionPixelSize(R.dimen.dynamic_grid_search_bar_height);
    
         将searchBarSpaceHeightPx=0;即可 
}

Launcher里面好多东西都是动态计算的,所以这里计算为0就行

4.修改主屏幕大小位置 (即图标 几*几)

DynamicGrid.java

public DynamicGrid(Context context, Resources resources,
                       int minWidthPx, int minHeightPx,
                       int widthPx, int heightPx,
                       int awPx, int ahPx) {
        DisplayMetrics dm = resources.getDisplayMetrics();
        ArrayList<DeviceProfile> deviceProfiles =
                new ArrayList<DeviceProfile>();
        boolean hasAA = !LauncherAppState.isDisableAllApps();
        DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
        // Our phone profiles include the bar sizes in each orientation
        deviceProfiles.add(new DeviceProfile("Super Short Stubby",
                255, 300,  2, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Shorter Stubby",
                255, 400,  3, 3,  48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
       
         /*chc edit*/     
        (客户要求2 * 2  ,找到对应的屏幕大小  修改 parameters 第4,5个即可 )     
        parameters  6:可以调整Icon的大小
        parameters  8:控制hotseatd的数量
        parameters  9:控制hotseatd的Icon大小
       deviceProfiles.add(new DeviceProfile("Short Stubby",
                275, 420,  2, 2,  70, 23, (hasAA ? 3 : 3), 53, R.xml.default_workspace_4x4));
      /*chc end */      


        deviceProfiles.add(new DeviceProfile("Stubby",
                255, 450,  2, 3,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus S",
                296, 491.33f,  4, 4,  48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
        /// M: add 294 X 460 profile
        deviceProfiles.add(new DeviceProfile("294 X 460",
                294, 460,  3, 3,  50, 25, (hasAA ? 5 : 5), 59, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus 4",
                335, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Nexus 5",
                359, 567,  4, 4,  DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
        deviceProfiles.add(new DeviceProfile("Large Phone",
                406, 694,  5, 5,  64, 14.4f,  5, 56, R.xml.default_workspace_5x5));
        // The tablet profile is odd in that the landscape orientation
        // also includes the nav bar on the side
        deviceProfiles.add(new DeviceProfile("Nexus 7",
                575, 904,  5, 6,  72, 14.4f,  7, 60, R.xml.default_workspace_5x6));
        // Larger tablet profiles always have system bars on the top & bottom
        deviceProfiles.add(new DeviceProfile("Nexus 10",
                727, 1207,  5, 6,  76, 14.4f,  7, 64, R.xml.default_workspace_5x6));
        deviceProfiles.add(new DeviceProfile("20-inch Tablet",
                1527, 2527,  7, 7,  100, 20,  7, 72, R.xml.default_workspace_4x4));
        mMinWidth = dpiFromPx(minWidthPx, dm);
        mMinHeight = dpiFromPx(minHeightPx, dm);
        mProfile = new DeviceProfile(context, deviceProfiles,
                mMinWidth, mMinHeight,
                widthPx, heightPx,
                awPx, ahPx,
                resources);
    }

5.禁止hotseat里面的Icon拖动,并且禁止形成文件夹

Launcher.java

public boolean onLongClick(View v) {
        ...
        CellLayout.CellInfo longClickCellInfo = null;
        View itemUnderLongClick = null;
        if (v.getTag() instanceof ItemInfo) {
            ItemInfo info = (ItemInfo) v.getTag();
            longClickCellInfo = new CellLayout.CellInfo(v, info);;
            itemUnderLongClick = longClickCellInfo.cell;
            resetAddInfo();
        }   
        /*chc add */     在此处进行判断是否在hotseat进行长按   
        boolean isHotseatbutten=false;
        if(longClickCellInfo!=null){
            isHotseatbutten= longClickCellInfo.container==-100? false:true;   //每一个Icon都有一个container的属性
//hostSeat:是-101  其他的是-100 

        }
        if(isHotseatbutten){
            return false;
        }
        /*chc end*/             
         final boolean inHotseat = isHotseatLayout(v);  //不知为何原因 此isHotseatLayout(v)并不能判断时候在hotseat区域 
         ...
    
        return true;
    }

禁止文件夹的形成
Workspace.java

boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,
            int[] targetCell, float distance, boolean external, DragView dragView,
            Runnable postAnimationRunnable) {
    ...
    /*chc add*/
        if(container==-101){
           return false;
        }
        /*chc end*/  
    ...
}

6.将文件夹修改为4宫格

FolderIcon.java

1:修改圆形成为正方形
FolderIcon.xml

<com.android.launcher3.FolderIcon
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:focusable="true" >
    <ImageView
        android:id="@+id/preview_background"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:antialias="true"
        android:src="@drawable/portal_ring_inner_holo"/> <!--将src换成正方形图标即可-->

2.修改缩略图为2*2

 // The number of icons to display in the
    private static final int NUM_ITEMS_IN_PREVIEW = 4;  //此处为文件夹显示缩略图的数量
 // The amount of vertical spread between items in the stack [0...1]
    private static final float PERSPECTIVE_SHIFT_FACTOR = 1.20f;  //值越大 缩略图越小


    private PreviewItemDrawingParams computePreviewItemDrawingParams(int index,
            PreviewItemDrawingParams params) {
              /*chc add */
                int index_order = index;
                final int previewPadding = FolderRingAnimator.sPreviewPadding;
               /*chc end*/

        // We want to imagine our coordinates from the bottom left, growing up and to the
        // right. This is natural for the x-axis, but for the y-axis, we have to invert things.
        float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
        float transX = offset + scaleOffsetCorrection;
        
         
        /*chc add */     在此处计算图标的位置 , 下面是自己计算图标的位置
            transX=1 * previewPadding +2;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize*2 + scaleOffsetCorrection)+previewPadding;
        if(index_order==1){
            transX=mBaselineIconSize+previewPadding*3;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize*2 + scaleOffsetCorrection)+previewPadding;
        }else if(index_order==2){           
            transX=1 * previewPadding +2;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize + scaleOffsetCorrection)+previewPadding*2;
        }else if(index_order==3){
            transX=mBaselineIconSize+previewPadding*3;
            transY=mAvailableSpaceInPreview - (mBaselineIconSize + scaleOffsetCorrection)+previewPadding*2;
        }
        
        /*chc end*/
        
        return params;
    }


  public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) {
         ....
                sSharedOuterRingDrawable = res.getDrawable(R.drawable.bg_rect);
                sSharedInnerRingDrawable = res.getDrawable(R.drawable.bg_rect);
                sSharedFolderLeaveBehind = res.getDrawable(R.drawable.bg_rect);  //此处替换文件夹托动处形成动画的图片 
            
      ...
            }
        }

7.Launcher修改成单层删除了google搜索无法显示删除APP按钮

问题3将google搜索return 成了null, 为了不占位置并且将他的高度修改成了0
所以导致了APP删除按钮的不显示
原因是google搜索包含了APP删除的按钮

所以现将问题3修改回来
Launcher.java

 public View getQsbBar() {
   ...
      if (widgetId != -1) {
                if (true) {   //chc  edit isSmallLandTablet()  to  true  这个是判断searchView 的加载模式
                                // 改成true是默认让他直接加载不要动态加载
                    mQsbView = getLayoutInflater().inflate(R.layout.qsb, mSearchDropTargetBar, false);  
                ..
                } else {
                    mQsb = mAppWidgetHost.createView(this, widgetId, searchProvider);                                  
                }
                    ///M.
                }
  }

修改qsb.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
     android:background="#00000000">  <!--chc eidt  修改背景为透明-->
   <!-- Global search icon -->
   <ImageView
        android:id="@+id/search_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:scaleType="center"
        android:visibility="gone"   <!--chc eidt  隐藏-->
        android:src="@drawable/ic_home_search_normal_holo"
        android:adjustViewBounds="true" />

    <!-- Voice search icon -->
    <ImageView
        android:id="@+id/voice_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:scaleType="center"
        android:src="@drawable/ic_home_voice_search_holo"
        android:adjustViewBounds="true"
        android:visibility="gone" <!--chc eidt  隐藏-->
        />
</LinearLayout>

修改完成删除App按钮可能会有点大
为了整体美观
修改问题3的search的高度进行适当调整
此问题结束

8.将安装的APP拖动至删除APP按钮 无法显示删除对话框,并且删除后重启有会还原

原因是将安装的APP 进行删除流程的时候判断成了Weight,所以导致删不了,并且不能弹出删除对话框

修改Launcher的加载模式进行对安装的APP进行flag标记
LauncherModel.java

private boolean loadWorkspace(){
 ...
while (!mStopped && c.moveToNext()) {
...
if (info != null) {
              //add by chc
         if(intent.getAction() != null && intent.getAction().equals(Intent.ACTION_MAIN)){
     try {
                                       
        final String packageName = intent.getComponent().getPackageName();
        //List<LauncherActivityInfoCompat> app = mLauncherApps.getActivityList(packageName, user);
        PackageInfo pi = manager.getPackageInfo(packageName, 0);
        if (!pi.applicationInfo.enabled) {
            // If we return null here, the corresponding item will be removed from the launcher
            // db and will not appear in the workspace.
            //return null;
            }
                                  
        final int appFlags = manager.getApplicationInfo(packageName, 0).flags;
        if ((appFlags & android.content.pm.ApplicationInfo.FLAG_SYSTEM) == 0) {
                info.flags |= AppInfo.DOWNLOADED_FLAG;                        
            if ((appFlags & android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    info.flags |= AppInfo.UPDATED_SYSTEM_APP_FLAG;
                }
            }
            //  info.firstInstallTime = manager.getPackageInfo(packageName, 0).firstInstallTime;
    } catch (NameNotFoundException e) {
        Log.d(TAG, "getPackInfo failed for componentName " + intent.getComponent());
            //return null;
    }
}
   // chc  add end
}

}

DeleteDropTarget.java
这里面是对删除的流程,在这里判断是否是安装的App,如果是安装的 就调用startApplicationUninstallActivity()进行删除

private void completeDrop(DragObject d) {
    if (isAllAppsApplication(d.dragSource, item)) {
    }
    ...
    else if (isWorkspaceOrFolderApplication(d)) {
     / /chc add if the dragview is install app that this methed will uninstalled else the shutcut delete it 
             if(item.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT){
                 ShortcutInfo shortcut = (ShortcutInfo) item;
                 final UserHandleCompat user = shortcut.user;
                 final ComponentName componentName = shortcut.intent.getComponent();
                 mLauncher.startApplicationUninstallActivity(componentName, shortcut.flags, user);
               }else{
                   LauncherModel.deleteItemFromDatabase(mLauncher, item);
               }
              //chc add end 
    }

}

此问题到此结束

9.将hotSeat中间图标变大 两边的缩小

CellLayout.java

 public boolean addViewToCellLayout(View child, int index, int childId, LayoutParams params,
            boolean markCells) {
       ...
        child.setScaleX(getChildrenScale());
        child.setScaleY(getChildrenScale());
        /*chc add */
        if(mIsHotseat){
            Log.d("cuihangchao","childId"+childId);
            if(lp.cellX!=1){
             child.setScaleX(0.8f);
                child.setScaleY(0.8f);
            }
        }
        /*chc end*/

        // Generate an id for each view, this assumes we have at most 256x256 cells
     ...
        return false;
    }

在此处判断hotseat是否是Hotseat上面的图标
然后根据ID, 将需要变动的进行响应的缩放
这样修改完成之后还有坑
会将大图标拖动到小图标上,或进行大图渲染,无法变成小图。重启后会还原。

最终修改方案
ShortcutAndWidgetContainer.java

@Override
    protected void dispatchDraw(Canvas canvas) {
        @SuppressWarnings("all") // suppress dead code warning
        final boolean debug = false;
       /*chc add */
        for (int i = getChildCount() - 1; i >= 0; i--) {
                final View child = getChildAt(i);           
                final CellLayout.LayoutParams lps = (CellLayout.LayoutParams) child.getLayoutParams();
                if(mIsHotseatLayout){   
                if(lps.cellX!=1){
                    child.setScaleX(0.7f);
                    child.setScaleY(0.7f);
                }
            }           
        }
        /*chc end*/ 
                                    
        if (debug) {
            // Debug drawing for hit space
            Paint p = new Paint();
            p.setColor(0x6600FF00);
            for (int i = getChildCount() - 1; i >= 0; i--) {
                final View child = getChildAt(i);
                final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();

                canvas.drawRect(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height, p);
            }
        }
        super.dispatchDraw(canvas);
    }

拖动的时候会不停的进入此方法,
所以在此方法里面进行判断,
将不会影响到渲染的效果

改这个问题的时候踩了好多的坑。
哎,踩了好多的坑

此问题到此结束

大概上面的修改launcher 的样子


图片发自简书App

MTK 7.0 Launcher3修改单层桌面

2.1删除Google搜索(packages\apps\Launcher3\res\values\dimens.xml )

 <dimen name="dynamic_grid_search_bar_height">6dp</dimen>  //留下 (卸载 移除 的高度,因为搜索和他们是包含的) 

Launcher.xml(注意找到对应分辨率)


 <include
           android:id="@+id/search_drop_target_bar"
           android:background="#00000000"
           layout="@layout/search_drop_target_bar"
       android:visibility="gone"
  /> 

com/android/launcher3/SearchDropTargetBar

 @Override
    public void onDragStart(DragSource source, Object info, int dragAction) {
        animateToState(State.DROP_TARGET, DEFAULT_DRAG_FADE_DURATION);          
          this.setVisibility(View.VISIBLE);  //拖动的时候将自己显示
          mQSB.setVisibility(View.GONE); //将QSB隐藏
         
    }


 @Override
    public void onDragEnd() {
        if (!mDeferOnDragEnd) {
            animateToState(State.SEARCH_BAR, DEFAULT_DRAG_FADE_DURATION);
        } else {
            mDeferOnDragEnd = false;
        }
       this.setVisibility(View.GONE);  //拖动结束的时候将自己隐藏
    }

 public void enableAccessibleDrag(boolean enable) {
        if (mQSB != null) {
            mQSB.setVisibility(View.GONE);  //直接将qsb自己隐藏,
        }
        mInfoDropTarget.enableAccessibleDrag(enable);
        mDeleteDropTarget.enableAccessibleDrag(enable);
        mUninstallDropTarget.enableAccessibleDrag(enable);
    }



删除移除按钮,单层桌面不需要移除
com/android/launcher3/DeleteDropTarget

@Override
    protected boolean supportsDrop(DragSource source, Object info) {
          if (info instanceof ShortcutInfo) {
                ShortcutInfo item = (ShortcutInfo) info;            
                return item.itemType !=           LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION;
            }
                  
          return info instanceof LauncherAppWidgetInfo;
    
        //return source.supportsDeleteDropTarget() && supportsDrop(info);
    }
到此,搜索就移除了,但是不影响拖动可卸载的应用进行卸载

2.2 将所有的应用加载到Workspace

/*chc add*/ 
    public void customBindWorkspaceItems() {
            final Context context = mApp.getContext();
            ArrayList<ItemInfo> tmpInfos;
            ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
            synchronized (sBgLock) {
                for (AppInfo app : mBgAllAppsList.data) {
                    tmpInfos = getItemInfoForComponentName(app.componentName, app.user);
                    if (tmpInfos.isEmpty()) {
                        // We are missing an application icon, so add this to the workspace
                        if(app.itemType!=LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { //不进行加载xml配置的Item
                            Log.d("Cuihangchao","app.title="+app.title);
                           added.add(app);
                        }
                        // This is a rare event, so lets log it
                        Log.e(TAG, "Missing Application on load: " + app);
                    }
                }
                if (!added.isEmpty()) {
                    addAndBindAddedWorkspaceItems(context,added);  //添加到Workspace
                }
            }
    
    }


LoaderTask的run()进行添加 

 public void run() {
            synchronized (mLock) {
          ...
            keep_running: {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                loadAndBindWorkspace();

                if (mStopped) {
                    LauncherLog.d(TAG, "LoadTask break in the middle, this = " + this);
                    break keep_running;
                }

                waitForIdle();

                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                loadAndBindAllApps();

                customBindWorkspaceItems();//chc add
            }
  3.新的应用安装增加到workspace

  PackageUpdatedTask 的run
  
  ...
public void run() {
            synchronized (mLock) {
     if (added != null) {
                
        final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added); //chc add
                addAndBindAddedWorkspaceItems(context, addedInfos);//chc add
                
                addAppsToAllApps(context, added);
                for (AppInfo ai : added) {
                    addedOrUpdatedApps.put(ai.componentName, ai);
                }
            }
...
}

到此,所有的应用都会加载到Workspace上面,不影响预制XML里面的应用进行重复加载    

2.3删除Allapp按钮

void resetLayout() {
        mContent.removeAllViewsInLayout();

        if(false){  //chc add 大家可以自己定义宏
            // Add the Apps button
            Context context = getContext();

            LayoutInflater inflater = LayoutInflater.from(context);
            TextView allAppsButton = (TextView)
                    inflater.inflate(R.layout.all_apps_button, mContent, false);
            Drawable d = context.getResources().getDrawable(R.drawable.all_apps_button_icon);

            mLauncher.resizeIconDrawable(d);
            int scaleDownPx = getResources().getDimensionPixelSize(R.dimen.all_apps_button_scale_down);
            Rect bounds = d.getBounds();
            d.setBounds(bounds.left, bounds.top + scaleDownPx / 2, bounds.right - scaleDownPx,
                    bounds.bottom - scaleDownPx / 2);
            allAppsButton.setCompoundDrawables(null, d, null, null);

            allAppsButton.setContentDescription(context.getString(R.string.all_apps_button_label));
            allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
            if (mLauncher != null) {
                mLauncher.setAllAppsButton(allAppsButton);
                allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
                allAppsButton.setOnClickListener(mLauncher);
                allAppsButton.setOnLongClickListener(mLauncher);
                allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
            }

            // Note: We do this to ensure that the hotseat is always laid out in the orientation of
            // the hotseat in order regardless of which orientation they were added
            int x = getCellXFromOrder(mAllAppsButtonRank);
            int y = getCellYFromOrder(mAllAppsButtonRank);
            CellLayout.LayoutParams lp = new CellLayout.LayoutParams(x,y,1,1);
            lp.canReorder = false;
            mContent.addViewToCellLayout(allAppsButton, -1, allAppsButton.getId(), lp, true);
        }
    }
//修复Bug。快速扔图标 图标变灰,并且不消失
  DragController.java

public boolean onTouchEvent(MotionEvent ev) {
  ...
case MotionEvent.ACTION_UP:
            // Ensure that we've processed a move event at the current pointer location.
            handleMoveEvent(dragLayerX, dragLayerY);
            mHandler.removeCallbacks(mScrollRunnable);

            if (mDragging) {
                //PointF vec = isFlingingToDelete(mDragObject.dragSource);  //检测是否是扔图标,                         

                PointF vec=null;// 删除扔图标操作,
                if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) {
                    vec = null;
                }
                Log.d("Cuihangchao","vec="+vec);
                if (vec != null) {
                    dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec);
                } else {
                    drop(dragLayerX, dragLayerY);
                }
            }
            endDrag();
...
}
  

到此,7.0的Launcher3就改成单层的了

附8.1修改https://blog.csdn.net/qq_30552095

此文会持续更新,有做Launcher的朋友可以参考参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,421评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 往日安静的楼上今天突然多了两位女人的争吵,恰巧在门外吸闲烟听出,原来是婆婆与儿媳妇之间的争吵,这是一个想到后就变得...
    Py17阅读 238评论 0 1