Android開發個人小記

1.finish Activity時軟鍵盤不關:在onPause時用InputMethodManagerhideSoftInputFromWindow關閉。
2.<layer-list>中的<item>android:gravity屬性以及android:heightandroid:widthandroid:height到API23之后才有的,別被AS忽悠了。
3.合并?selectableItemBackground與你自己的背景資源

無法直接用xml定義layer-list,因為drawable屬性不支持attr值
需要用代碼實現:

// Attribute array
int[] attrs = new int[] { android.R.attr.selectableItemBackground };
TypedArray a = getTheme().obtainStyledAttributes(attrs);
// Drawable held by attribute 'selectableItemBackground' is at index '0'
Drawable d = a.getDrawable(0);
a.recycle();

之后創建 LayerDrawable

LayerDrawable ld = new LayerDrawable(new Drawable[] {
                       // Nine Path Drawable
                       getResources().getDrawable(R.drawable.Your_Nine_Path),
                       // Drawable from attribute
                       d });
// Set the background to 'ld'
yourLayoutContainer.setBackground(ld);
4.無法啟用Hierarchy View解決方案:

在環境變量中添加ANDROID_HVPROTO=ddm

5.RatingBar組件流血效果解決方式:

切的星星底部留2個像素高的透明像素

6.點擊波紋效果屬性
  • android:background="?selectableItemBackground"有邊界效果
  • android:background="?selectableItemBackgroundBorderless"無邊界效果
7.在LinearLayout里增加了個分割線** ( Android3.0+版本 ) **

必要屬性:

  • android:divider,分割線圖片
  • android:showDividers,分割線位置
8.RadioButton&RadioGroup使用注意:
  • RadioGroup繼承自LinearLayout
  • RadioButton變化事件還是監聽其click事件,然后獲取isChecked()
  • 設置<RadioGroup>的默認選中項
    • 代碼中radiogroup.check(idOfRadioButton)
    • xml中直接使用<RadioGroup>android:checkedButton屬性指定默認被選中的RadioButton的id

    注意:用 android:checkedButton指選中的RadioButton的id時要有+號,因為 <RadioButton>定義在 <RadioGroup>后面,不加+會報找不到id錯誤。

9.在代碼中使用 ?selectableItemBackground
int[] attrs = new int[] { R.attr.selectableItemBackground};
TypedArray ta = themedContext.obtainStyledAttributes(attrs);
Drawable drawableFromTheme = ta.getDrawable(0);
ta.recycle();
10.代碼中使用<selector>顏色,使用ResourcesgetColorStateList方法獲取,如
radioButton.setTextColor(getResources().getColorStateList(R.color.sl_rb_filter_item));
11.代碼中引用繼承形式的style,點用下劃線替換如
<style name="AppTheme.PopupMenu">
  <item name="android:itemTextAppearance">@style/ItemTextStyle.AppTheme</item>
</style>

代碼中用使用R.style.AppTheme_PopupMenu

12.自定義PopMenu的字體與分隔線
<style name="AppTheme.PopupMenu">
  <!--<item name="android:itemTextAppearance">@style/ItemLargeTextStyle.AppTheme</item>--><!-- 這樣也是可以的! -->
  <item name="textAppearanceLargePopupMenu">@style/ItemLargeTextStyle.AppTheme</item>
  <item name="textAppearanceSmallPopupMenu">@style/ItemSmallTextStyle.AppTheme</item>
  <item name="android:dropDownListViewStyle">@style/PopupMenuListView</item>
</style>

<style name="ItemLargeTextStyle.AppTheme" parent="TextAppearance.AppCompat.Widget.PopupMenu.Large">
  <item name="android:textColor">@color/popup_menu_item_text_color</item>
  <item name="android:textSize">16sp</item>
</style>

<style name="ItemSmallTextStyle.AppTheme" parent="TextAppearance.AppCompat.Widget.PopupMenu.Small">
  <item name="android:textColor">@color/popup_menu_item_text_color</item>
  <item name="android:textSize">16sp</item>
</style>

<style name="PopupMenuListView" parent="@style/Widget.AppCompat.ListView.DropDown">
  <item name="android:divider">@color/divide_color</item>
  <item name="android:dividerHeight">0.5dp</item>
</style>
13.上下級View的狀態傳遞
  • 父傳子android:duplicateParentState="true"
  • 子傳父android:addStatesFromChildren="true"
14.RadioButton的padding是很坑的哦

API17+時 paddingLeft 是圖標與文字的間隔,也就是設置paddingLeft小圈圈位置是不變的喲

15.View即使在Activity中,View的getContext()方法不一定返回的Context不一定是對應的Activity,有可能是ContextWrapper的子類如TintContextWrapperContextThemeWrapper,可以使用下面的方法獲取Activity:
private static Activity scanForActivity(Context cont) {
    if (cont == null)
        return null;
    else if (cont instanceof Activity)
        return (Activity)cont;
    else if (cont instanceof ContextWrapper)
        return scanForActivity(((ContextWrapper)cont).getBaseContext());
    return null;
}
16.水平布局的LinearLayout中有子View的android:layout_gravity="bottom"沒有用,解決方法是在LinearLayout中添加:

android:baselineAligned="false"

17.布局中關閉某View的硬件圖層加速

android:layerType=software

18.無線調試(wifi debug)方法
  • 方法一
    1.先連USB,開啟debug。
    2.用adb shell netcfg命令查看手機ip,蘋果系統adb shell ip route
    3.用命令adb connect <DEVICE_IP_ADDRESS>:5555連接。
    4.可以拔USB線了。
    5.adb -s <DEVICE_IP_ADDRESS>:5555 usb關閉。
  • 方法二(針對有些高端設備設置里有Wifi調試開關)
    1.進入開發者選項,找到ADB over network(在USB debugging下面),開啟它。
    2.上面的設置項顯示了地址和端口號,PC用命令adb connect <DEVICE_IP_ADDRESS>:<port>連接。
    3.關閉的話直接在設置里關。
  • Android Studio有一個無線調試的插件
19.自定義SeekBar,點點與線線不對齊問題

android:thumbOffset="0dp"

20.用RadioButtonsetButtonDrawable(null)在部分機器上(華為)沒卵用問題

使用setButtonDrawable(new StateListDrawable())

21.PopupWindow點擊外面隱藏

只要有背景就行了,mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT))

22.PopupWindow彈出后背后的界面黑化

步驟:

  • 獲取PopupWindow根視圖了,有背景View會多一層,M之后也會多一層。
  • 使用WindowManager.LayoutParamsFLAG_DIM_BEHIND設置黑化,以及dimAmount設置黑化程度。

代碼:

View container;
if (mPopupWindow.getBackground() == null) {
  if (VERSION.SDK_INT >= VERSION_CODES.M){
    container = (View) mPopupWindow.getContentView().getParent();
  } else {
    container = mPopupWindow.getContentView();
  }
} else {
  if (VERSION.SDK_INT >= VERSION_CODES.M) {
    container = (View) mPopupWindow.getContentView().getParent().getParent();
  } else {
    container = (View) mPopupWindow.getContentView().getParent();
  }
}
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
wm.updateViewLayout(container, p);

23.獲取狀態欄高度

Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;

24.播放音頻時要先獲取音頻焦點

25.ActivityDialogFragment的回調丟失問題,在onCreate判斷savedInstanceState是否為null,若否說明是重新恢復的Activity,根據tag獲取了DialogFragment然后重新設置一下回調。

26.創建一個不用輸入就有提示的AutoCompleteTextView
繼承AutoCompleteTextView,重寫enoughToFilteronFocusChanged兩個方法:

@Override
public boolean enoughToFilter() {
  return true;
}

@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
  super.onFocusChanged(focused, direction, previouslyFocusedRect);
  if (focused && getAdapter() != null) {
    performFiltering("", KeyEvent.KEYCODE_UNKNOWN);
    showDropDown();
  }
}

27.讀取當前theme的屬性

TypedValue tv = new TypedValue();
if (getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) {
  int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());
}

28.AppBarLayout的addOnOffsetChangedListener可以添加垂直偏移事件監聽

mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
  @Override
  public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
    Log.d("tag_scroll", "recycler_view current offset: "+verticalOffset);
  }
});

29.RatingBar的高度用wrap_content在23之前是沒用的,高度會變0哦,請使用minHeight

30.RadioButton的選中圈不設置方式setButtonDrawable(new StateListDrawable())

31.RadioButton在4.3以下先設置padding,再設置背景,padding會失效,得先調用setBackgroundDrawable再調setPadding

32.DialogFragment把title藏起來的方式整理。

//方式一
public static MyDialogFragment newInstance() {
  MyDialogFragment mDialogFragment = new MyDialogFragment();
  //Set Arguments here if needed for dialog auto recreation on screen rotation
  mDialogFragment.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
  return mDialogFragment;
}

//方式二(不適用于用onCreateView創建界面的`DialogFragment`)
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
  Dialog dialog = super.onCreateDialog(savedInstanceState);
  // request a window without the title
  dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
  return dialog;
}

//方式三(和一差不多,也是用setStyle方法)
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setStyle(STYLE_NO_TITLE, 0);
}

33.DialogFragment定義高寬方式(特適用于沒有Title且用onCreateView創建界面的)

public void onResume() {
  super.onResume();
  Window window = getDialog().getWindow();
  window.setLayout(width, height);
  window.setGravity(Gravity.CENTER);
  //TODO:
}

34.顯示密碼方法

checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
  @Override
  public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if(!isChecked) {
      passwordEt.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
    } else {
      passwordEt.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
    }
  }
});

35.兩種獲取屏幕參數的方式

WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = window.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();

DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
int width = metrics.widthPixels;
int height = metrics.heightPixels;

36.系統組件declare-styleable位置

/frameworks/base/core/res/res/values/attrs.xml

37.用Appcompat時獲取Activity引用
由于Context會被包裝成ContextWrapper,直接getContext()不能直接cast成Activity

private Activity getActivity() {
  Context context = getContext();
  while (context instanceof ContextWrapper) {
    if (context instanceof Activity) {
      return (Activity)context;
    }
    context = ((ContextWrapper)context).getBaseContext();
  }
  return null;
}

38.用文件轉Drawable或Bitmap

//For a Drawable
String pathName = "/path/to/file/xxx.jpg";
Drawable d = Drawable.createFromPath(pathName);

//For a Bitmap:
Bitmap b = BitmapFactory.decodeFile(pathName);

39.查找無用資源
在AndroidStudio中Menu ->Analyze -> Run Inspection by Name ->輸入 Unused resources

40.使用action跳轉到Activity

  • AndroidManifest中對應的Activity添加
<intent-filter>
    <action android:name="com.you.name.action" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
  • 啟動代碼
Intent intent = new Intent("com.you.name.action");
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    //tell user the activity couldn't reach
}

41.監聽鍵盤是否開啟的正確姿勢
來自這里

boolean mKeyboardOpen;
private void addKeyboardVisibleListener() {
    final View activityRootView = ((ViewGroup)findViewById(android.R.id.content)).getChildAt(0);
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            Rect r = new Rect();
            //r will be populated with the coordinates of your view that area still visible.
            activityRootView.getWindowVisibleDisplayFrame(r);

            int rootViewHeight = activityRootView.getRootView().getHeight();
            int heightDiff = rootViewHeight - (r.bottom - r.top);
            Cog.d(TAG, "heightDiff=", heightDiff);
            if (heightDiff > rootViewHeight / 4 && !mKeyboardOpen) { // if more than 100 pixels, its probably a keyboard...
                mKeyboardOpen = true;
            } else {
                mKeyboardOpen = false;
            }
        }
    });
}

如果使用下面的方式,只能配合在Android Manifest中設置android:windowSoftInputMode="adjustResize"才有效

int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > dpToPx(this, 200)) { // if more than 200 dp, it's probably a keyboard...
      // ... do something here
}

高度變化判斷不能簡單與100比較,在有NavigationBar的機器上會有問題。1/4根布局高度試下來可以。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容