Android開發百科全書③

Android 存儲路徑

Environment.getExternalStorageDirectory()	
context.getExternalFilesDir(dir)	
context.getExternalCacheDir()	
ExternalCacheDir: /storage/emulated/0/Android/data/com.womai/cache  
ExternalStorageDirectory: /storage/emulated/0   
ExternalStorageState:mounted


context.getFilesDir()	
context.getCacheDir()
getFilesDir: /data/user/0/com.womai/files   
CacheDir: /data/user/0/com.womai/cache    
ExternalCacheDir:/storage/emulated/0/Android/data/com.womai/cache

android 關於dialog全屏和非全屏設置

爲了將dialog設置爲全屏,我們經常在佈局文件中將父控件寬高設置爲math_parent,但是發現效果並沒有像我們想象的實現全屏。甚至我們將style設置爲true但是也並沒有什麼效果。下面說說我的方法吧,寫的不好的地方,希望指正啊。
方法一:
dialog設置全屏方法一:獲取屏幕的大小,然後設置dialog的寬高爲屏幕的寬高。
Display display = getWindow().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
//設置dialog的寬高爲屏幕的寬高
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(width, height);
setContentView(view, layoutParams)
方法二:
下面這行代碼一定要放在setContentView(view);後面執行。layoutParams一定要設置爲MATH_PARENT,同理,如果只是想將dialog設置爲內容包裹,則將layoutParams設置爲WRAP_CONTENT即可。
getWindow().setLayout((ViewGroup.LayoutParams.MATCH_PARENT), ViewGroup.LayoutParams.MATCH_PARENT);

監聽橫豎屏切換

1、AndroidManifest.xml中將activity 代碼如下:

<activity  
android:name="com.suma.smartview.activity.LTVDetailActivity"
android:configChanges="keyboardHidden|orientation|screenSize"/>
<activity>  

2、代碼裏碼如下:

public void onConfigurationChanged(Configuration newConfig) { 
super.onConfigurationChanged(newConfig); 
//切換爲豎屏 
if (newConfig.orientation == Configuration .ORIENTATION_PORTRAIT) { 

 } else if (newConfig.orientation == Configuration .ORIENTATION_LANDSCAPE) {
 }
}

解決ViewPager使用setCurrentItem跨距離(中間間隔多個page頁)切換過渡動畫閃現問題

在這裏插入圖片描述
爲什麼我沒有設置過渡動畫,且只用了setCurrentItem(int item)方法卻出現了這種情況?

setCurrentItem(int item)源碼分析

    /**
     * Set the currently selected page. If the ViewPager has already been through its first
     * 設置切換到當前選定頁。如果ViewPager已經通過其與當前適配器的第一個佈局
     * layout with its current adapter there will be a smooth animated transition between
     * 將有一個平滑的動畫過渡當前item和指定item之間。
     * the current item and the specified item.
     *
     * @param item Item index to select
     */
    public void setCurrentItem(int item) {
        mPopulatePending = false;
        setCurrentItemInternal(item, !mFirstLayout, false);
    }

也就是說,ViewPager在通過其與當前適配器的第一個佈局後,在當前item與指定item切換時,還是會存在一個平滑的過渡動畫,這也是我們多頁面切換時出現問題的病症所在,這裏主要是由mFirstLayout來控制——源碼中的mFirstLayout默認值爲true,在onLayout方法中又變動其值爲false.

setCurrentItem(int item, boolean smoothScroll)源碼分析
那麼如果使用ViewPager類中與setCurrentItem(int item)比較相似的setCurrentItem(int item, boolean smoothScroll)呢?我們先來看下它的源碼:

    /**
     * Set the currently selected page.
     * 設置切換到當前選擇的頁面
     * @param item Item index to select 選定頁面的下標
     * @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
     * true:平滑滾動到新的item,false:立即滾動到指定位置.
     */
    public void setCurrentItem(int item, boolean smoothScroll) {
        mPopulatePending = false;
        setCurrentItemInternal(item, smoothScroll, false);
    }

通過對setCurrentItem(int item, boolean smoothScroll)源碼的分析,我們可以發現,當我們使用其代替setCurrentItem(int item)進行使用時,爲了避免跨距離切換出現上述異常情況,我們只需要設置smoothScroll = false,關閉過渡動畫即可解決。

解決方法

使用setCurrentItem(int item,boolean smoothScroll)方法
在跨距離切換的時候,使用setCurrentItem(position,false)方法來操作即可解決問題。
參數item:目標頁的位置;
參數smoothScroll:是否平滑過渡(true:是,false:否)。

決ViewPager跨距離(中間間隔多個page頁)切換過渡動畫閃現問題

圓形圓角的幾種實現方式

(一)自定義圓形圓角ImageView庫地址

compile ‘com.makeramen:roundedimageview:2.3.0’


xml中屬性:
riv_border_width: 邊框寬度
riv_border_color: 邊框顏色
riv_oval: 是否圓形
riv_corner_radius: 圓角弧度
riv_corner_radius_top_left:左上角弧度
riv_corner_radius_top_right: 右上角弧度
riv_corner_radius_bottom_left:左下角弧度
riv_corner_radius_bottom_right:右下角弧度

在xml佈局中實現佈局
<com.makeramen.roundedimageview.RoundedImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/avatar"
        app:riv_border_color="#333333"
        app:riv_border_width="2dp"
        app:riv_oval="true" />

(二)Glide實現圓角、圓形圖

用三方庫 compile 'jp.wasabeef:glide-transformations:2.0.1’
Glide V3 實現圓圖

 Glide.with((Activity) t).load(url)
 .bitmapTransform(new CropCircleTransformation((Activity) t))
 .into(imageView);
 

Glide V3 實現圓角

Glide.with((Activity) t)
.load(url)
.dontTransform().
bitmapTransform(new RoundedCornersTransformation((Activity) t, cornerValue, 0, RoundedCornersTransformation.CornerType.ALL))
.into(imageView);

(三)自定義實現

public class MyRoundImageView extends ImageView {
    private int defaultRadius;
    private int radius;
    private int leftTopRadius;
    private int rightTopRadius;
    private int rightBottomRadius;
    private int leftBottomRadius;
    float width, height;
    public MyRoundImageView(Context context) {
        this(context, null);
        init(context, null);
    }

    public MyRoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        init(context, attrs);
    }

    public MyRoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        if (Build.VERSION.SDK_INT < 18) {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }

        defaultRadius = SysUtils.dipToPx(context,6);
        if(attrs!=null){
            // 讀取配置
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.Custom_Round_Image_View);
            radius = array.getDimensionPixelOffset(R.styleable.Custom_Round_Image_View_radius, defaultRadius);
            leftTopRadius = array.getDimensionPixelOffset(R.styleable.Custom_Round_Image_View_left_top_radius, defaultRadius);
            rightTopRadius = array.getDimensionPixelOffset(R.styleable.Custom_Round_Image_View_right_top_radius, defaultRadius);
            rightBottomRadius = array.getDimensionPixelOffset(R.styleable.Custom_Round_Image_View_right_bottom_radius, defaultRadius);
            leftBottomRadius = array.getDimensionPixelOffset(R.styleable.Custom_Round_Image_View_left_bottom_radius, defaultRadius);

            //如果四個角的值沒有設置,那麼就使用通用的radius的值。
            if (defaultRadius == leftTopRadius) {
                leftTopRadius = radius;
            }
            if (defaultRadius == rightTopRadius) {
                rightTopRadius = radius;
            }
            if (defaultRadius == rightBottomRadius) {
                rightBottomRadius = radius;
            }
            if (defaultRadius == leftBottomRadius) {
                leftBottomRadius = radius;
            }
            array.recycle();
        }else {
            leftTopRadius = rightTopRadius = rightBottomRadius = leftBottomRadius = defaultRadius;
        }




    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getWidth();
        height = getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //這裏做下判斷,只有圖片的寬高大於設置的圓角距離的時候才進行裁剪
        int maxLeft = Math.max(leftTopRadius, leftBottomRadius);
        int maxRight = Math.max(rightTopRadius, rightBottomRadius);
        int minWidth = maxLeft + maxRight;
        int maxTop = Math.max(leftTopRadius, rightTopRadius);
        int maxBottom = Math.max(leftBottomRadius, rightBottomRadius);
        int minHeight = maxTop + maxBottom;
        if (width >= minWidth && height > minHeight) {
            Path path = new Path();
            //四個角:右上,右下,左下,左上
            path.moveTo(leftTopRadius, 0);
            path.lineTo(width - rightTopRadius, 0);
            path.quadTo(width, 0, width, rightTopRadius);

            path.lineTo(width, height - rightBottomRadius);
            path.quadTo(width, height, width - rightBottomRadius, height);

            path.lineTo(leftBottomRadius, height);
            path.quadTo(0, height, 0, height - leftBottomRadius);

            path.lineTo(0, leftTopRadius);
            path.quadTo(0, 0, leftTopRadius, 0);

            canvas.clipPath(path);
        }
        super.onDraw(canvas);
    }

    public void SetRoundValue(float radius) {

        leftTopRadius = rightTopRadius = rightBottomRadius = leftBottomRadius = defaultRadius = (int) radius;
        invalidate();
    }
}

attr.xml 註冊屬性

    <declare-styleable name="Custom_Round_Image_View">
        <attr name="radius" format="dimension"/>
        <attr name="left_top_radius" format="dimension"/>
        <attr name="right_top_radius" format="dimension"/>
        <attr name="right_bottom_radius" format="dimension"/>
        <attr name="left_bottom_radius" format="dimension"/>
    </declare-styleable>

Suggestion: use tools:overrideLibrary="" to force usage

應用在Android Studio Build的時候,拋出瞭如下異常:

Error:Execution failed for task ‘:app:processInternalDebugManifest’.

Manifest merger failed : uses-sdk:minSdkVersion 11 cannot be smaller than version 14 declared in library [fm.jiecao:jiecaovideoplayer:4.5_preview1] E:\workspace\XWorld\app\build\intermediates\exploded-aar\fm.jiecao\jiecaovideoplayer\4.5_preview1\AndroidManifest.xml
Suggestion: use tools:overrideLibrary=“fm.jiecao.jcvideoplayer_lib” to force usage
錯誤原因:

出現這個錯誤的原因是我引入的第三方庫最低支持版本高於我的項目的最低支持版本,異常中的信息顯示:我的項目的最低支持版本爲8(Android 2.2),而第三方庫的最低支持版本爲9(Android 2.3),所以拋出了這個異常。

解決辦法:

在AndroidManifest.xml文件中 標籤中添加,其中的xxx.xxx.xxx爲第三方庫包名,如果存在多個庫有此異常,則用逗號分割它們,例如:,這樣做是爲了項目中的AndroidManifest.xml和第三方庫的AndroidManifest.xml合併時可以忽略最低版本限制。

How do I use tools:overrideLibrary in a build.gradle file?

add  <uses-sdk tools:overrideLibrary="android.support.v17.leanback"/>
don't forget to include 
xmlns:tools="http://schemas.android.com/tools" too, before the <application> tag

過濾GA一些錯誤日誌,不上報

重寫ExceptionHandler .

    /**
     * GA 發送異常信息
     *
     * @param debugMode
     */
    public void sendException(boolean debugMode) {
        if (debugMode) {
            return;
        }
        try {
            String deviceName = SysUtils.getSystemModel();
            if (!TextUtils.isEmpty(deviceName) && deviceName.contains(Device_OPPO)) {
                //用於分析TimeOut事件,是否由oppo r9 引起
                return;
            }
            Tracker t = getGATracker(MyApp.TrackerName.APP_TRACKER);
            Thread.UncaughtExceptionHandler myHandler = new NewExceptionReporter(
                    t,
                    Thread.getDefaultUncaughtExceptionHandler(),
                    getApplication());
            // Make myHandler the new default uncaught exception handler.
            Thread.setDefaultUncaughtExceptionHandler(myHandler);
        } catch (RuntimeException e) {
            return;
        } catch (Exception e) {
            return;
        }
    }

根據Thread 與 Exception類型區分,上不上報。

/**
 * 重寫 UncaughtExceptionHandler  過濾錯誤
 * @date 2019-12-31
 */
public class NewExceptionReporter extends ExceptionReporter {
    public NewExceptionReporter(Tracker tracker, Thread.UncaughtExceptionHandler uncaughtExceptionHandler, Context context) {
        super(tracker, uncaughtExceptionHandler, context);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        Log.e("uncaughtException",""+thread.getName()+"  "+throwable.toString()+"  "+(throwable instanceof ArithmeticException));
        if (thread.getName().contains("Finalizer") && throwable instanceof ArithmeticException) {
            //ignore it
        } else {
            super.uncaughtException(thread, throwable);
        }

    }
}
歡迎愛學習的小夥伴加羣一起進步:230274309 。 一起分享,一起進步!少划水,多曬乾貨!!歡迎大家!!!(進羣潛水者勿加)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章