指定回数だけ action を実行します。
val count = supportFragmentManager.backStackEntryCount
repeat(count) {
supportFragmentManager.popBackStack()
}
class SimpleDragView : FrameLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
private val targetView: View
private val gestureDetector: GestureDetector
init {
val size = (100 * resources.displayMetrics.density).toInt()
targetView = View(context).apply {
layoutParams = LayoutParams(size, size)
setBackgroundColor(Color.RED)
}
addView(targetView)
gestureDetector =
GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onScroll(
e1: MotionEvent,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
targetView.translationX -= distanceX
targetView.translationY -= distanceY
return true
}
override fun onDown(e: MotionEvent): Boolean {
val pointerIndex = e.actionIndex
val x = e.getX(pointerIndex)
val y = e.getY(pointerIndex)
if (!(x.toInt() in 0..width && y.toInt() in 0..height)) {
return false
}
val left = targetView.translationX
val right = left + targetView.width
val top = targetView.translationY
val bottom = top + targetView.height
if (!(x in left..right && y in top..bottom)) {
return false
}
return true
}
})
gestureDetector.setIsLongpressEnabled(false)
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(ev) || super.onTouchEvent(ev)
}
}
file:///android_asset/index.html
class SimpleDragView : FrameLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
)
private var activePointerId = INVALID_POINTER_ID
private var lastTouchX = 0f
private var lastTouchY = 0f
private val targetView: View
init {
val size = (100 * resources.displayMetrics.density).toInt()
targetView = View(context).apply {
layoutParams = LayoutParams(size, size)
setBackgroundColor(Color.RED)
}
addView(targetView)
}
override fun onTouchEvent(ev: MotionEvent): Boolean {
when (ev.actionMasked) {
MotionEvent.ACTION_DOWN -> {
val pointerIndex = ev.actionIndex
val x = ev.getX(pointerIndex)
val y = ev.getY(pointerIndex)
if (!(x.toInt() in 0..width && y.toInt() in 0..height)) {
return false
}
val left = targetView.translationX
val right = left + targetView.width
val top = targetView.translationY
val bottom = top + targetView.height
if (!(x in left..right && y in top..bottom)) {
return false
}
lastTouchX = x
lastTouchY = y
activePointerId = ev.getPointerId(0)
}
MotionEvent.ACTION_MOVE -> {
if (activePointerId == INVALID_POINTER_ID) {
return false
}
val pointerIndex = ev.findPointerIndex(activePointerId)
val x = ev.getX(pointerIndex)
val y = ev.getY(pointerIndex)
if (!(x.toInt() in 0..width && y.toInt() in 0..height)) {
return false
}
val diffX = x - lastTouchX
val diffY = y - lastTouchY
targetView.translationX += diffX
targetView.translationY += diffY
lastTouchX = x
lastTouchY = y
}
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> {
activePointerId = INVALID_POINTER_ID
}
MotionEvent.ACTION_POINTER_UP -> {
if (activePointerId == INVALID_POINTER_ID) {
return false
}
val pointerIndex = ev.actionIndex
if (ev.getPointerId(pointerIndex) != activePointerId) {
return false
}
val newPointerIndex = if (pointerIndex == 0) 1 else 0
val x = ev.getX(newPointerIndex)
val y = ev.getY(newPointerIndex)
if (!(x.toInt() in 0..width && y.toInt() in 0..height)) {
activePointerId = INVALID_POINTER_ID
return false
}
lastTouchX = x
lastTouchY = y
activePointerId = ev.getPointerId(newPointerIndex)
}
}
return true
}
}
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="dialogCornerRadius">12dp</item>
</style>
(<item name="android:dialogCornerRadius">12dp</item> だと Android Pie(API Level 28)以降だけ角丸になります。)
<item name="buttonBarPositiveButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog</item>
<item name="buttonBarNegativeButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog</item>
<item name="buttonBarNeutralButtonStyle">@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush</item>
↓
<item name="android:textColor">@color/mtrl_text_btn_text_color_selector</item>
↓
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="1.00" android:color="?attr/colorPrimary" .../>
<item android:alpha="0.60" android:color="?attr/colorOnSurface" .../>
<item android:alpha="1.00" android:color="?attr/colorPrimary" .../>
<item android:alpha="0.38" android:color="?attr/colorOnSurface"/>
</selector>
あー、colorPrimary と colorOnSurface になったのねぇ。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccent" android:state_enabled="true"/>
<item android:color="@color/mtrl_btn_text_color_disabled"/>
</selector>
<style name="ThemeOverlay.MyApp.MaterialAlertDialog" parent="ThemeOverlay.MaterialComponents.MaterialAlertDialog">
<item name="buttonBarPositiveButtonStyle">@style/Widget.MyApp.Button.TextButton.Dialog</item>
<item name="buttonBarNegativeButtonStyle">@style/Widget.MyApp.Button.TextButton.Dialog</item>
</style>
<style name="Widget.MyApp.Button.TextButton.Dialog" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">#1565C0</item>
</style>
AlertDialog.Builder(this, R.style.ThemeOverlay_MyApp_MaterialAlertDialog)
.setTitle("Title")
.setMessage("Message")
.setPositiveButton(android.R.string.ok, null)
.setNegativeButton(android.R.string.cancel, null)
.show()
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="7dp"
android:left="7dp"
android:right="7dp"
android:top="7dp">
<selector>
<item android:state_checked="true">
<shape android:shape="oval">
<size
android:width="18dp"
android:height="18dp" />
<stroke
android:width="6dp"
android:color="#6666ff" />
</shape>
</item>
<item>
<shape android:shape="oval">
<size
android:width="18dp"
android:height="18dp" />
<stroke
android:width="2dp"
android:color="#cccccc" />
</shape>
</item>
</selector>
</item>
</layer-list>
<CheckBox
...
android:button="@drawable/checkbox"
... />
<CheckBox
...
android:button="@drawable/checkbox"
app:useMaterialThemeColors="false"
... />
android {
...
defaultConfig {
...
manifestPlaceholders = [facebookAppId: "1234567890000000"]
}
...
}
dependencies {
...
implementation "com.facebook.android:facebook-android-sdk:6.1.0"
implementation "com.facebook.android:facebook-share:6.1.0"
}
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application
...>
...
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="${facebookAppId}" />
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProvider${facebookAppId}"
android:exported="true" />
</application>
</manifest>
java.lang.ExceptionInInitializerError Caused by: The SDK has not been initialized, make sure to call FacebookSdk.sdkInitialize() first.
// Package private for testing only
static void loadDefaultsFromMetadata(Context context) {
if (context == null) {
return;
}
ApplicationInfo ai = null;
try {
ai = context.getPackageManager().getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
return;
}
if (ai == null || ai.metaData == null) {
return;
}
if (applicationId == null) {
Object appId = ai.metaData.get(APPLICATION_ID_PROPERTY);
if (appId instanceof String) {
String appIdString = (String) appId;
if (appIdString.toLowerCase(Locale.ROOT).startsWith("fb")) {
applicationId = appIdString.substring(2);
} else {
applicationId = appIdString;
}
} else if (appId instanceof Integer) {
throw new FacebookException(
"App Ids cannot be directly placed in the manifest." +
"They must be prefixed by 'fb' or be placed in the string resource file.");
}
}
...
}
ここの処理を読むと、appId の最初に fb or FB がついているときはそれを省いた部分を applicationId にしていることがわかります。
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
...
<application
...>
...
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="fb${facebookAppId}" />
<provider
android:name="com.facebook.FacebookContentProvider"
android:authorities="com.facebook.app.FacebookContentProvider${facebookAppId}"
android:exported="true" />
</application>
</manifest>
<string name="facebook_app_id">1234567890000000</string>
とか
android {
...
defaultConfig {
...
resValue "string", "facebook_app_id", "1234567890000000"
}
...
}
のときは、fb を付けなくても com.facebook.sdk.ApplicationId の値は String として読み込まれます。
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />