從Github開源項目《雲閱》所學到的知識

 

感謝開源,感謝大神,才讓咱們這些菜鳥成長!html

附上雲閱開源項目地址:點我吧。java

 

1.輪播圖的實現。

  如今的APP基本都會實現這個功能吧,而後一直都找不到好的第三方庫,可以知足各類需求。然而碰到了這個開源庫...react

 

 

2.MVVM-DataBinding架構開發。

  它本質上就是MVC、MVP的改進版。實現數據和視圖相互綁定。MVVM就是講其中的View的狀態和行爲抽象化,讓咱們將視圖UI和業務邏輯分開。android

  • gradle配置:    (在module的build.gradle中的android模塊中加入以下代碼塊) 
 dataBinding {
        enabled = true
    }

 

 

3.解決Bug:Android點擊應用圖標後會從新進入啓動頁。

 

 

4.第三方庫Glide的簡單使用。

  • gradle配置:
implementation 'com.github.bumptech.glide:glide:4.7.1'
implementation 'jp.wasabeef:glide-transformations:2.0.1

  

 

5.分包策略,解決65535方法限制的問題。

  • gradle配置:
 implementation 'com.android.support:multidex:1.0.3'

 

 

6.避免在1s中屢次點擊按鈕。

  方法:本身新建一個抽象類,集成OnClickListener,重寫裏面的onClick函數。git

public abstract class PerfectClickListener implements OnClickListener {
    public static final int MIN_CLICK_DELAY_TIME = 1000;
    private long lastClickTime = 0;
    private int id = -1;

    @Override
    public void onClick(View v) {
        long currentTime = Calendar.getInstance().getTimeInMillis();
        int mId = v.getId();
        if (id != mId) {
            id = mId;
            lastClickTime = currentTime;
            onNoDoubleClick(v);
            return;
        }
        if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
            lastClickTime = currentTime;
            onNoDoubleClick(v);
        }
    }

    protected abstract void onNoDoubleClick(View v);
}
View Code

  使用場景:在啓動頁中,有一個跳轉按鈕,避免用戶屢次點擊啓動多個主頁。github

 

 

7.如何使用android.support.v7.widget.Toolbar

  • 首先必定要在build.gradle中添加依賴。
 implementation "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
    implementation "com.android.support:design:$rootProject.supportLibraryVersion"
    implementation "com.android.support:support-v4:$rootProject.supportLibraryVersion"
    implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"

  這裏使用了rootProject來間接設置,注意這個rootProject要在項目的build.gradle中具體配置。具體百度吧。web

  • 而後再佈局中這樣用。
 <android.support.v7.widget.Toolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
                 android:layout_height="?attr/actionBarSize"
                 android:background="@color/colorTheme"
                 app:contentInsetStart="0.0dp"
                 app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                 app:theme="@style/ToolbarStyle">

  這裏使用了自定義主題,在style文件中本身建立一個。canvas

 

 

 

8.設置主題點擊波紋效果。

  • 首先得引入谷歌的材料設計庫,上面第7點中有相關引入方式。
  • 而後再佈局文件中:android:background="?attr/...."   (這裏省略號寫一些波紋樣式便可)
  • 參考文章:https://yq.aliyun.com/articles/12407

 

 

9.左右滑動ViewPager時,沒獲取焦點沒響應。

  原來僅僅是在定義Viewpager的時候,添加以下代碼便可。緩存

android:descendantFocusability="blocksDescendants"
      beforeDescendants:viewgroup會優先其子類控件而獲取到焦點

        afterDescendants:viewgroup只有當其子類控件不須要獲取焦點時才獲取焦點

        blocksDescendants:viewgroup會覆蓋子類控件而直接得到焦點

 

 

10.設置狀態欄顏色以及其餘方法。

  • 首先自定義一個視圖叫作StatusBarView。
public class StatusBarView extends View {
    public StatusBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public StatusBarView(Context context) {
        super(context);
    }
}
  • 而後寫一個通用類,統一設置狀態欄的一些屬性。
public class StatusBarUtil {

    public static final int DEFAULT_STATUS_BAR_ALPHA = 112;

    /**
     * 設置狀態欄顏色
     *
     * @param activity 須要設置的 activity
     * @param color    狀態欄顏色值
     */
    public static void setColor(Activity activity, @ColorInt int color) {
        setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
    }

    /**
     * 設置狀態欄顏色
     *
     * @param activity       須要設置的activity
     * @param color          狀態欄顏色值
     * @param statusBarAlpha 狀態欄透明度
     */

    public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            int count = decorView.getChildCount();
            if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
                decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
            } else {
                StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
                decorView.addView(statusView);
            }
            setRootView(activity);
        }
    }

    /**
     * 設置狀態欄純色 不加半透明效果
     *
     * @param activity 須要設置的 activity
     * @param color    狀態欄顏色值
     */
    public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {
        setColor(activity, color, 0);
    }

    /**
     * 設置狀態欄顏色(5.0如下無半透明效果,不建議使用)
     *
     * @param activity 須要設置的 activity
     * @param color    狀態欄顏色值
     */
    @Deprecated
    public static void setColorDiff(Activity activity, @ColorInt int color) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        // 生成一個狀態欄大小的矩形
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int count = decorView.getChildCount();
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.getChildAt(count - 1).setBackgroundColor(color);
        } else {
            StatusBarView statusView = createStatusBarView(activity, color);
            decorView.addView(statusView);
        }
        setRootView(activity);
    }

    /**
     * 使狀態欄半透明
     * <p>
     * 適用於圖片做爲背景的界面,此時須要圖片填充到狀態欄
     *
     * @param activity 須要設置的activity
     */
    public static void setTranslucent(Activity activity) {
        setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);
    }

    /**
     * 使狀態欄半透明
     * <p>
     * 適用於圖片做爲背景的界面,此時須要圖片填充到狀態欄
     *
     * @param activity       須要設置的activity
     * @param statusBarAlpha 狀態欄透明度
     */
    public static void setTranslucent(Activity activity, int statusBarAlpha) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        setTransparent(activity);
        addTranslucentView(activity, statusBarAlpha);
    }

    /**
     * 針對根佈局是 CoordinatorLayout, 使狀態欄半透明
     * <p>
     * 適用於圖片做爲背景的界面,此時須要圖片填充到狀態欄
     *
     * @param activity       須要設置的activity
     * @param statusBarAlpha 狀態欄透明度
     */
    public static void setTranslucentForCoordinatorLayout(Activity activity, int statusBarAlpha) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        transparentStatusBar(activity);
        addTranslucentView(activity, statusBarAlpha);
    }

    /**
     * 設置狀態欄全透明
     *
     * @param activity 須要設置的activity
     */
    public static void setTransparent(Activity activity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        transparentStatusBar(activity);
        setRootView(activity);
    }

    /**
     * 使狀態欄透明(5.0以上半透明效果,不建議使用)
     * <p>
     * 適用於圖片做爲背景的界面,此時須要圖片填充到狀態欄
     *
     * @param activity 須要設置的activity
     */
    @Deprecated
    public static void setTranslucentDiff(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 設置狀態欄透明
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            setRootView(activity);
        }
    }

    /**
     * 爲DrawerLayout 佈局設置狀態欄變色
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     * @param color        狀態欄顏色值
     */
    public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
        setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);
    }

    /**
     * 爲DrawerLayout 佈局設置狀態欄顏色,純色
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     * @param color        狀態欄顏色值
     */
    public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
        setColorForDrawerLayout(activity, drawerLayout, color, 0);
    }

    /**
     * 爲DrawerLayout 佈局設置狀態欄變色
     *
     * @param activity       須要設置的activity
     * @param drawerLayout   DrawerLayout
     * @param color          狀態欄顏色值
     * @param statusBarAlpha 狀態欄透明度
     */
    public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,
                                               int statusBarAlpha) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        // 生成一個狀態欄大小的矩形
        // 添加 statusBarView 到佈局中
        ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
        if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {
            contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
        } else {
            StatusBarView statusBarView = createStatusBarView(activity, color);
            contentLayout.addView(statusBarView, 0);
        }
        // 內容佈局不是 LinearLayout 時,設置padding top
        if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
            contentLayout.getChildAt(1)
                    .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
                            contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
        }
        // 設置屬性
        ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
        drawerLayout.setFitsSystemWindows(false);
        contentLayout.setFitsSystemWindows(false);
        contentLayout.setClipToPadding(true);
        drawer.setFitsSystemWindows(false);

        addTranslucentView(activity, statusBarAlpha);
    }

    /**
     * 爲DrawerLayout 佈局設置狀態欄變色(5.0如下無半透明效果,不建議使用)
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     * @param color        狀態欄顏色值
     */
    @Deprecated
    public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // 生成一個狀態欄大小的矩形
            ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
            if (contentLayout.getChildCount() > 0 && contentLayout.getChildAt(0) instanceof StatusBarView) {
                contentLayout.getChildAt(0).setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));
            } else {
                // 添加 statusBarView 到佈局中
                StatusBarView statusBarView = createStatusBarView(activity, color);
                contentLayout.addView(statusBarView, 0);
            }
            // 內容佈局不是 LinearLayout 時,設置padding top
            if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
                contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
            }
            // 設置屬性
            ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
            drawerLayout.setFitsSystemWindows(false);
            contentLayout.setFitsSystemWindows(false);
            contentLayout.setClipToPadding(true);
            drawer.setFitsSystemWindows(false);
        }
    }

    /**
     * 爲 DrawerLayout 佈局設置狀態欄透明
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     */
    public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
        setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);
    }

    /**
     * 爲 DrawerLayout 佈局設置狀態欄透明
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     */
    public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int statusBarAlpha) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        setTransparentForDrawerLayout(activity, drawerLayout);
        addTranslucentView(activity, statusBarAlpha);
    }

    /**
     * 爲 DrawerLayout 佈局設置狀態欄透明
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     */
    public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }

        ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
        // 內容佈局不是 LinearLayout 時,設置padding top
        if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
            contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
        }

        // 設置屬性
        ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
        drawerLayout.setFitsSystemWindows(false);
        contentLayout.setFitsSystemWindows(false);
        contentLayout.setClipToPadding(true);
        drawer.setFitsSystemWindows(false);
    }

    /**
     * 爲 DrawerLayout 佈局設置狀態欄透明(5.0以上半透明效果,不建議使用)
     *
     * @param activity     須要設置的activity
     * @param drawerLayout DrawerLayout
     */
    @Deprecated
    public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 設置狀態欄透明
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // 設置內容佈局屬性
            ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
            contentLayout.setFitsSystemWindows(true);
            contentLayout.setClipToPadding(true);
            // 設置抽屜佈局屬性
            ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);
            vg.setFitsSystemWindows(false);
            // 設置 DrawerLayout 屬性
            drawerLayout.setFitsSystemWindows(false);
        }
    }

    /**
     * 爲頭部是 ImageView 的界面設置狀態欄全透明
     *
     * @param activity       須要設置的activity
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTransparentForImageView(Activity activity, View needOffsetView) {
        setTranslucentForImageView(activity, 0, needOffsetView);
    }

    /**
     * 爲頭部是 ImageView 的界面設置狀態欄透明(使用默認透明度)
     *
     * @param activity       須要設置的activity
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTranslucentForImageView(Activity activity, View needOffsetView) {
        setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
    }

    /**
     * 爲頭部是 ImageView 的界面設置狀態欄透明
     *
     * @param activity       須要設置的activity
     * @param statusBarAlpha 狀態欄透明度
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
            activity.getWindow()
                    .getDecorView()
                    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
           if (activity instanceof TabActivity){
               activity.getWindow()//兼容TabActivity
                       .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
           }
        } else {
            activity.getWindow()
                    .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        addTranslucentView(activity, statusBarAlpha);
        if (needOffsetView != null) {
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
            if (layoutParams != null) {
                layoutParams.setMargins(0, getStatusBarHeight(activity), 0, 0);
            }
        }
    }

    public static void setMargin(Activity activity, View needOffsetView) {
        if (needOffsetView != null) {
            ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
            if (layoutParams != null) {
                layoutParams.setMargins(0, getStatusBarHeight(activity), 0, 0);
            }
        }
    }


    /**
     * 爲 fragment 頭部是 ImageView 的設置狀態欄透明
     *
     * @param activity       fragment 對應的 activity
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {
        setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
    }

    /**
     * 爲 fragment 頭部是 ImageView 的設置狀態欄透明
     *
     * @param activity       fragment 對應的 activity
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {
        setTranslucentForImageViewInFragment(activity, 0, needOffsetView);
    }

    /**
     * 爲 fragment 頭部是 ImageView 的設置狀態欄透明
     *
     * @param activity       fragment 對應的 activity
     * @param statusBarAlpha 狀態欄透明度
     * @param needOffsetView 須要向下偏移的 View
     */
    public static void setTranslucentForImageViewInFragment(Activity activity, int statusBarAlpha, View needOffsetView) {
        setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            clearPreviousSetting(activity);
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private static void clearPreviousSetting(Activity activity) {
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int count = decorView.getChildCount();
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.removeViewAt(count - 1);
            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setPadding(0, 0, 0, 0);
        }
    }

    /**
     * 添加半透明矩形條
     *
     * @param activity       須要設置的 activity
     * @param statusBarAlpha 透明值
     */
    private static void addTranslucentView(Activity activity, int statusBarAlpha) {
        ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
        if (contentView.getChildCount() > 1) {
            contentView.getChildAt(1).setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
        } else {
            contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
        }
    }

    /**
     * 生成一個和狀態欄大小相同的彩色矩形條
     *
     * @param activity 須要設置的 activity
     * @param color    狀態欄顏色值
     * @return 狀態欄矩形條
     */
    private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color) {
        // 繪製一個和狀態欄同樣高的矩形
        StatusBarView statusBarView = new StatusBarView(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(color);
        return statusBarView;
    }

    /**
     * 生成一個和狀態欄大小相同的半透明矩形條
     *
     * @param activity 須要設置的activity
     * @param color    狀態欄顏色值
     * @param alpha    透明值
     * @return 狀態欄矩形條
     */
    private static StatusBarView createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
        // 繪製一個和狀態欄同樣高的矩形
        StatusBarView statusBarView = new StatusBarView(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
        return statusBarView;
    }

    /**
     * 設置根佈局參數
     */
    private static void setRootView(Activity activity) {
        ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
        rootView.setFitsSystemWindows(true);
        rootView.setClipToPadding(true);
    }

    /**
     * 使狀態欄透明
     */
    @TargetApi(Build.VERSION_CODES.KITKAT)
    private static void transparentStatusBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 建立半透明矩形 View
     *
     * @param alpha 透明值
     * @return 半透明 View
     */
    private static StatusBarView createTranslucentStatusBarView(Activity activity, int alpha) {
        // 繪製一個和狀態欄同樣高的矩形
        StatusBarView statusBarView = new StatusBarView(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
        return statusBarView;
    }

    /**
     * 獲取狀態欄高度
     *
     * @param context context
     * @return 狀態欄高度
     */
    public static int getStatusBarHeight(Context context) {
        // 得到狀態欄高度
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        return context.getResources().getDimensionPixelSize(resourceId);
    }

    /**
     * 計算狀態欄顏色
     *
     * @param color color值
     * @param alpha alpha值
     * @return 最終的狀態欄顏色
     */
    private static int calculateStatusColor(@ColorInt int color, int alpha) {
        float a = 1 - alpha / 255f;
        int red = color >> 16 & 0xff;
        int green = color >> 8 & 0xff;
        int blue = color & 0xff;
        red = (int) (red * a + 0.5);
        green = (int) (green * a + 0.5);
        blue = (int) (blue * a + 0.5);
        return 0xff << 24 | red << 16 | green << 8 | blue;
    }

}
View Code
  • 簡單用法:根據本身需求在須要的地方,StatusBarUtil.set相關的方法便可。

 

 

11.常見的item點擊的效果樣式文件。

  長按或者點擊一個TextView以後,背景顏色更改,通常都是初始爲白色,長按後顯示灰色。顏色值也是很講究的。微信

  有點相似微信頁面每個item點擊的效果,一直調不出那樣的效果。主要是找不到合適的顏色。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_enabled="false">
        <shape>
            <solid android:color="#F1F3F4" />
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#d9d9d9" />
        </shape>
    </item>
    <item android:state_pressed="false">
        <shape>
            <solid android:color="#F1F3F4" />
        </shape>
    </item>

</selector>

 

 

 12.用SharePerferences文件來記錄全局配置。

  能夠寫一個通用類,用來封裝不一樣數據類型寫入文件,從文件中獲取數據的方法。

public class SPUtils {

    private static final String CONFIG = "config";

    /**
     * 獲取SharedPreferences實例對象
     *
     * @param fileName
     */
    private static SharedPreferences getSharedPreference(String fileName) {
        return MyApplication.getInstance().getSharedPreferences(fileName, Context.MODE_PRIVATE);
    }

    /**
     * 保存一個String類型的值!
     */
    public static void putString(String key, String value) {
        SharedPreferences.Editor editor = getSharedPreference(CONFIG).edit();
        editor.putString(key, value).apply();
    }

    /**
     * 獲取String的value
     */
    public static String getString(String key, String defValue) {
        SharedPreferences sharedPreference = getSharedPreference(CONFIG);
        return sharedPreference.getString(key, defValue);
    }

    /**
     * 保存一個Boolean類型的值!
     */
    public static void putBoolean(String key, Boolean value) {
        SharedPreferences.Editor editor = getSharedPreference(CONFIG).edit();
        editor.putBoolean(key, value).apply();
    }

    /**
     * 獲取boolean的value
     */
    public static boolean getBoolean(String key, Boolean defValue) {
        SharedPreferences sharedPreference = getSharedPreference(CONFIG);
        return sharedPreference.getBoolean(key, defValue);
    }

    /**
     * 保存一個int類型的值!
     */
    public static void putInt(String key, int value) {
        SharedPreferences.Editor editor = getSharedPreference(CONFIG).edit();
        editor.putInt(key, value).apply();
    }

    /**
     * 獲取int的value
     */
    public static int getInt(String key, int defValue) {
        SharedPreferences sharedPreference = getSharedPreference(CONFIG);
        return sharedPreference.getInt(key, defValue);
    }

    /**
     * 保存一個float類型的值!
     */
    public static void putFloat(String fileName, String key, float value) {
        SharedPreferences.Editor editor = getSharedPreference(fileName).edit();
        editor.putFloat(key, value).apply();
    }

    /**
     * 獲取float的value
     */
    public static float getFloat(String key, Float defValue) {
        SharedPreferences sharedPreference = getSharedPreference(CONFIG);
        return sharedPreference.getFloat(key, defValue);
    }

    /**
     * 保存一個long類型的值!
     */
    public static void putLong(String key, long value) {
        SharedPreferences.Editor editor = getSharedPreference(CONFIG).edit();
        editor.putLong(key, value).apply();
    }

    /**
     * 獲取long的value
     */
    public static long getLong(String key, long defValue) {
        SharedPreferences sharedPreference = getSharedPreference(CONFIG);
        return sharedPreference.getLong(key, defValue);
    }

    /**
     * 取出List<String>
     *
     * @param key     List<String> 對應的key
     * @return List<String>
     */
    public static List<String> getStrListValue(String key) {
        List<String> strList = new ArrayList<String>();
        int size = getInt(key + "size", 0);
        //Log.d("sp", "" + size);
        for (int i = 0; i < size; i++) {
            strList.add(getString(key + i, null));
        }
        return strList;
    }

    /**
     * 存儲List<String>
     * @param key     List<String>對應的key
     * @param strList 對應須要存儲的List<String>
     */
    public static void putStrListValue(String key, List<String> strList) {
        if (null == strList) {
            return;
        }
        // 保存以前先清理已經存在的數據,保證數據的惟一性
        removeStrList(key);
        int size = strList.size();
        putInt(key + "size", size);
        for (int i = 0; i < size; i++) {
            putString(key + i, strList.get(i));
        }
    }

    /**
     * 清空List<String>全部數據
     *
     * @param key     List<String>對應的key
     */
    public static void removeStrList(String key) {
        int size = getInt(key + "size", 0);
        if (0 == size) {
            return;
        }
        remove(key + "size");
        for (int i = 0; i < size; i++) {
            remove(key + i);
        }
    }

    /**
     * 清空對應key數據
     */
    public static void remove(String key) {
        SharedPreferences.Editor editor = getSharedPreference(CONFIG).edit();
        editor.remove(key).apply();
    }

}
View Code

   另外,能夠根據本身的需求,靈活地在文件中增長一些具體的方法。好比存儲APP的夜間模式或者日間模式,是否登陸等。

 

 

13.利用Glide畫圓角圖。  

  • 首先在module的build.gradle中添加依賴,前面第4點有講過。
  • 而後再自定義一個轉換器,相似於下面這樣。
public class GlideCircleTransform extends BitmapTransformation {

    public GlideCircleTransform(Context context) {
        super(context);
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return circleCrop(pool, toTransform);
    }

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {
        if (source == null) return null;
        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
        // TODO this could be acquired from the pool too
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        }
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }

    @Override
    public String getId() {
        return getClass().getName();
    }
}
View Code
  • 而後就是Glide調用這個轉換器了,相似於下面這樣。
public static void displayCircle(ImageView imageView, String imageUrl) {
        Glide.with(imageView.getContext())
                .load(imageUrl)
                .crossFade(500)
                .error(R.drawable.ic_avatar_default)
                .transform(new GlideCircleTransform(imageView.getContext()))
                .into(imageView);
    }

 

 

 

14.學會添加library。

  這裏添加library不是在build.gradle中添加依賴,也不是在工程中添加libs文件。而是導入一個Module。

  實際上是一個主項目須要實現某些功能,而後將這部分功能劃分開來,最後將這部分功能集成到主項目中,也是是模塊的劃分,因此這裏稱爲module。

  這樣的好處是:能夠再主module中任何地方引用子module的圖片資源,代碼資源等等。

  如今有一個地方不是特別理解,就是如何將多個library統一放在一個文件夾下面,這樣方便管理,否則都不知道哪一個是主項目了。

  添加單個library參考文章:https://blog.csdn.net/u014772414/article/details/51194952

 

 

 

15.學會定義BaseFragment。

  主要抓住一下要點吧。

  • 若是網絡異常,則頁面應該怎麼顯示。
  • 若是正在加載中,則頁面應該怎麼顯示。
  • 如何動態添加本身想要的佈局。

   因此在佈局方面咱們能夠這樣佈局。

        <RelativeLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!--加載失敗-->
            <LinearLayout
                android:id="@+id/ll_error_refresh"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:orientation="vertical"
                android:visibility="gone">

                <ImageView
                    android:id="@+id/img_err"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/load_err" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="15dp"
                    android:text="加載失敗,點擊重試"
                    android:textSize="14sp" />
            </LinearLayout>

            <!--加載中..-->
            <LinearLayout
                android:id="@+id/ll_progress_bar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="80dp"
                android:gravity="center_vertical">

                <ImageView
                    android:id="@+id/img_progress"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:src="@drawable/yun_anim" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:text="努力加載中..."
                    android:textColor="@color/colorTabText"
                    android:textSize="14sp" />

            </LinearLayout>

        </RelativeLayout>
View Code

  而後再BaseFragment中,這樣決定怎麼隱藏怎麼顯示。

public abstract class BaseFragment<SV extends ViewDataBinding> extends Fragment {

    protected SV bindingView;//佈局view
    protected boolean mIsVisible=false;//fragment是否顯示了
    private LinearLayout mLlProgressBar;//加載中
    private LinearLayout mRefresh;//加載失敗
    protected RelativeLayout mContainer;//內容佈局
    private AnimationDrawable mAnimationDrawable;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View ll = inflater.inflate(R.layout.fragment_base, null);
        bindingView = DataBindingUtil.inflate(getActivity().getLayoutInflater(),
                setContent(), null, false);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        bindingView.getRoot().setLayoutParams(params);
        mContainer = ll.findViewById(R.id.container);
        mContainer.addView(bindingView.getRoot());//動態替換成本身想要的佈局
        return ll;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mLlProgressBar = getView(R.id.ll_progress_bar);
        ImageView img = getView(R.id.img_progress);

        // 加載動畫
        mAnimationDrawable = (AnimationDrawable) img.getDrawable();
        // 默認進入頁面就開啓動畫
        if (!mAnimationDrawable.isRunning()) {
            mAnimationDrawable.start();
        }
        mRefresh = getView(R.id.ll_error_refresh);
        // 點擊加載失敗佈局
        mRefresh.setOnClickListener(new PerfectClickListener() {
            @Override
            protected void onNoDoubleClick(View v) {
                showLoading();
                onRefresh();
            }
        });
        bindingView.getRoot().setVisibility(View.GONE);

    }

    protected <T extends View> T getView(int id) {
        return (T) getView().findViewById(id);
    }

    /**
     * 加載失敗後點擊後的操做
     */
    protected void onRefresh() {

    }

    /**
     * 顯示加載中狀態
     */
    protected void showLoading() {
        if (mLlProgressBar.getVisibility() != View.VISIBLE) {
            mLlProgressBar.setVisibility(View.VISIBLE);
        }
        // 開始動畫
        if (!mAnimationDrawable.isRunning()) {
            mAnimationDrawable.start();
        }
        if (bindingView.getRoot().getVisibility() != View.GONE) {
            bindingView.getRoot().setVisibility(View.GONE);
        }
        if (mRefresh.getVisibility() != View.GONE) {
            mRefresh.setVisibility(View.GONE);
        }
    }

    /**
     * 加載完成的狀態
     */
    protected void showContentView() {
        if (mLlProgressBar.getVisibility() != View.GONE) {
            mLlProgressBar.setVisibility(View.GONE);
        }
        // 中止動畫
        if (mAnimationDrawable.isRunning()) {
            mAnimationDrawable.stop();
        }
        if (mRefresh.getVisibility() != View.GONE) {
            mRefresh.setVisibility(View.GONE);
        }
        if (bindingView.getRoot().getVisibility() != View.VISIBLE) {
            bindingView.getRoot().setVisibility(View.VISIBLE);
        }
    }

    /**
     * 加載失敗點擊從新加載的狀態
     */
    protected void showError() {
        if (mLlProgressBar.getVisibility() != View.GONE) {
            mLlProgressBar.setVisibility(View.GONE);
        }
        // 中止動畫
        if (mAnimationDrawable.isRunning()) {
            mAnimationDrawable.stop();
        }
        if (mRefresh.getVisibility() != View.VISIBLE) {
            mRefresh.setVisibility(View.VISIBLE);
        }
        if (bindingView.getRoot().getVisibility() != View.GONE) {
            bindingView.getRoot().setVisibility(View.GONE);
        }
    }

    /**
     * 佈局
     */
    public abstract int setContent();

    /**
     * 在這裏實現Fragment數據的緩加載.
     */
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (getUserVisibleHint()) {
            mIsVisible = true;
            loadData();
        } else {
            mIsVisible = false;

        }
    }

    /**
     * 顯示時加載數據,須要這樣的使用
     * 注意聲明 isPrepared,先初始化
     * 生命週期會先執行 setUserVisibleHint 再執行onActivityCreated
     * 在 onActivityCreated 以後第一次顯示加載數據,只加載一次
     */
    protected void loadData() {
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}
View Code

 

 

 

16.ViewModel使用方法。

   implementation 'android.arch.lifecycle:extensions:1.1.0'
    implementation 'android.arch.lifecycle:reactivestreams:1.1.0'

 

 

 

17.RxJava+RxAndroid的學習。

  做用:RxJava是一個Android中的響應式實現,RxAndroid將異步UI事件封裝起來。

  參考文章:http://www.javashuo.com/article/p-mgjetrgr-dy.html

  github地址:https://github.com/ReactiveX/RxJava  和  https://github.com/ReactiveX/RxAndroid

 

 

 

18.首頁功能完成。

  只要研究好一個頁面,基本上其餘頁面都不在話下了。

  由於這個頁面,進行了網絡請求,視圖綁定,BaseFragment定義,接口API請求等,基本上能作的事情,這個頁面都會作。

  除此以外,還有一些通用的工具包,首頁Bean類型的定義,首頁的佈局文件,抽屜的佈局,只不過沒有處理點擊事件。

  預覽頁面以下:

  

  而後僅僅完成首頁以後,我進行打包,方便之後使用。

  百度雲連接:https://pan.baidu.com/s/1VCiuVy21RLMOHflN9MP19A      

  密碼:hmci

  以後的過程應該就是觸類旁通了!

  這裏我總結一下過程:(想到哪寫到哪)

      1.首先定義了一個抽象類BaseFragment,讓這個每日推薦的Fragment來繼承它。不僅僅繼承,還要求傳入一個泛型類,這個泛型類繼承ViewDataBinding。

        這裏就是爲了方便處理數據的,由於用到MVVM模式,全部聲明瞭layout的視圖都生成一個視圖綁定類,進而能夠獲取到數據。我的以爲就是爲了簡化

        從視圖中findViewById的過程,其實在用的時候,仍是有一次賦值的過程,不過就不用之前那麼麻煩地看視圖id了。 

        言歸正傳,這個BaseFragment一樣繼承了Fragment,注意是v4的Fragment,這裏是一坑。

        而後這個BaseFragment主要幹什麼?

        佈局很簡單,最外層LinearLayout,裏面一個RelativeLayout,再裏面就是兩個LinearLayout,分別是正在加載和加載失敗的圖片及文字的顯示。

        因此啊,佈局中的RelativeLayout其實就是顯示內容的,要麼這個內容爲正在加載,要麼爲加載失敗,要麼就是內容了,就這三種狀況。

        值得一提的是,使用MVVM模式是如何將內容添加到這個RelativeLayout中呢?

        這裏實際上是用了DataBindingUtil.inflate方法,動態生成一個泛型類(繼承於ViewDataBinding),而後用RelativeLayout.addView方法添加便可。

        回想一下Fragment的生命週期~

        首先onAttach->onCreateView->onCreate->onActivityCreate->onStart->onResume,到這裏視圖才能真正展現。。。

        因此在onActivityCreate中能夠作什麼呢?

        答案固然就是:開啓動畫啦。而後就是設置失敗刷新的點擊事件。反正這裏就是須要幹嗎就幹嗎。

        而後還有一些方法,好比顯示加載中狀態,加載完成狀態,加載失敗狀態,主要處理視圖的隱藏,這裏仍是簡單。主要方便繼承者調用嘛。

        重要點1:而後就是實現Fragment數據的緩加載,其實就是判斷fragment是否可見,可見才進行請求。

        重要點2:而後須要添加一條消息,就是你數據在一個子線程裏請求請求請求...完成以後,要經過一條消息發送給主線程,主線程來處理數據。

               注意在onDestroy中,將這條消息取消掉,不然內存泄漏就慘咯,而後本身也寫一個移除方法。 

 

      2.好了,如今有BaseFragment了。那麼如今還須要對當前頁面單獨設置一個接口,用來實現僅僅這個頁面纔會作的一些方法。

        對於主頁來講,我須要顯示輪播圖,顯示主頁列表,顯示主頁錯誤頁面,顯示旋轉動畫,取主頁緩存。

 

      3.而後就是EverydayFragment的具體實現了,原來在這裏面才真正開啓動畫的,因此這樣的話會更加靈活處理各類頁面動畫。

        原來這裏不是用的BaseFragment中的動畫,他是本身單獨寫的一個動畫。因此在它本身的佈局中有一個獨特的動畫圖。

        這裏的須要定義一個相似於以前MVP模式中的P(presenter),這裏由於用到MVVM模式,因此效果是同樣的,不過這裏名字爲viewModel了。

 

      4.來看一下這個處理器吧。(我習慣稱處理網絡請求的東西叫作處理器,不過這裏進行了兩次封裝,還有一個我就叫具體網絡請求器吧)

        這裏還包裝了一層,將真正的網絡請求封裝了。

        首先看一下第一層處理器。

        在構造器裏面創建了一個具體網絡請求器的實例。這個能夠叫作建立型模式吧。

        簡單理一下網絡數據加載過程:

          在處理器中調用了網絡請求器的同名的方法,用了一個接口做爲回調3種狀況,1個是成功,1個是加載失敗,1個是添加消息給basefragment。

          若是加載成功,則顯示數據,而後將緩存清理,從新添加最新的緩存。若是沒有數據列表,則從緩存中拿,緩存也沒有,則從新請求。

          若是加載失敗,就嘗試從緩存中讀取,若是緩存有數據,就顯示列表數據。若是緩存也沒數據,則顯示BaseFragment中定義的錯誤界面。

        而後看一些這個具體網絡請求器幹了些什麼?

          首先是具體請求輪播圖。調用的過程真的太講究了,得好好學學別人的封裝過程。

          首先是定義了一個同名的請求方法後,裏面傳入了一個接口,主要是處理具體的回調。

        網絡封裝過程:

          首先HttpClient是一個網絡請求類,這是一個接口。由於每一個接口會有一個BaseUrl。

          這個HttpClient裏面有一個Builder類,裏面處理各類請求,返回的都是HttpClient對象。

          爲何會返回HttpClient對象呢?由於這裏還用了一個BuildFactory類,來封裝Retrofit請求,設置一些請求參數等。

          最後仍是要回到HttpClient,而後這裏面還有請求的具體參數寫的API請求,返回Observable<T>類型數據。

        

        5.獲取到網絡數據後該怎麼顯示呢?

          答案就是適配器了。

          在哪裏設置適配器?

          這個就得看着本身了,在繼承BaseFragment的類中設置。在這個繼承BaseFragment中有不少實例,如綁定Header佈局對象,綁定Footer佈局對象,

            當前Fragment的適配器,當前Fragment的ViewModel。

          這個Header佈局對象就是當前Fragment頁面最上方的佈局,一個banner,一個4個圖標入口。使用RecycleView.addHeaderView方法便可。

          若是RecyclerView滑動不流暢,需設置recylerView.setNestedScrollingEnabled(false);

          注意在onPause中中止所有圖片請求,在onResume繼續圖片請求。

          這個適配器就是處理數據顯示的一個關鍵類了。

          首先他繼承了BaseRecyclerViewAdapter,無賴,只能硬着頭皮先看BaseRecyclerViewAdapter了。

          這個BaseRecyclerViewAdapter也是繼承了RecyclerView.Adapter<BaseRecyclerViewHolder>,無賴,還得先了解BaseRecyclerViewHolder啦

          BaseRecyclerViewHolder主要就是一個視圖持有者,居然定義了兩個泛型,T是咱們的數據類型,D是一個視圖綁定類。

          由於繼承了RecyclerView.ViewHolder,那麼它的做用也就是容納視圖的做用了。因此這個BaseRecyclerVIewHolder的做用就是執行

            ViewDataBinding的一個executePendingBindings方法而已。

          BaseRecyclerViewAdapter因此就該實現父類中定義的抽象方法onBindViewHolder了。其餘就是一些數據的增長刪除獲取了。

          EverydayAdapter正是繼承了BaseRecyclerViewAdapter了,而後具體實現了兩個必須實現的方法,getItemViewType,onCreateViewHolder了

 

 

19.對於適配器中的getItemViewType的理解。

  如今才真正理解適配器中的函數。

  其實裏面的position,並非一開始就加載完。而是加載到手機屏幕高度,就是說position只會填充完當前手機屏幕。

  而後滑動手機屏幕後,這個position纔會作相應的改變。

 

 

20.學會了自定義處理WebView的活動(通用)。

  如今的APP基本都會用到webView,特別是相似於微信那種自帶進度條的WebView很常見。

  因此如今新建了一個專門處理webView的活動,可能只是這個項目通用吧,不一樣項目根據本身需求酌情修改便可。

  這個網頁能夠處理不少東西,撥打電話,發送短信,上傳圖片,播放視頻,循環顯示網頁標題,進度條,能夠說比較通用吧。

  參考文章:https://github.com/youlookwhat/WebViewStudy

  

          

21.之後再補充。

相關文章
相關標籤/搜索