[Twitter] モーメント並べ替え時の「問題が発生しました」への対処法
Twitterでモーメントを編集する際、ツイートを新しい順へ並べ替えしようとすると、「問題が発生しました。しばらくしてからやりなおしてください。」と表示され、並べ替えできないことがありました。
その場合、
バグによりモーメント上で重複しているツイートの片方をモーメント上から削除
することによって、並べ替えできるようになりました。
ソート時にツイート時間が同じ値の場合エラーとして処理しているんですかねー。
そういえば、現在モーメントの編集は旧デザインのWeb版からのみ行える(自動でそっちに遷移する)んですが、旧デザインが2020年6月1日より閉鎖されてしまうので、編集できなくなるのかモーメント自体廃止されるのか新デザインでできるようになるのか…
追記: モーメント編集ページのみ旧デザインのまま残りました。
[Twitter] 画像をオリジナルサイズで表示する (2019)
画像URL形式変更後のTwitterで、オリジナルサイズの画像を表示する方法を紹介します。
仕様変更前に画像URL末尾に「:orig」を付けることで表示できたアレです。
手順
1. 画像をブラウザで開く
Twitterのスマートフォンアプリを利用している場合は、ツイートメニューからツイートのURLをコピーするなどして、ブラウザ上でツイートを開きます。
ブラウザ上で、ツイートの画像を長押しや右クリックして直リンクで開きます。
URLが「https://pbs.twimg.com/media/XXX?format=XXX&name=XXX」のような形式であればOKです。
2. URLを変更する
画像URLの「&name=」の後ろを「orig」に変更して表示します。
例えばURLが
https://pbs.twimg.com/media/XXX?format=XXX&name=medium
の場合、
https://pbs.twimg.com/media/XXX?format=XXX&name=orig
と変更します。
以上でオリジナルサイズが表示されます。
ブラウザの拡張機能を使う
ブラウザの拡張機能を使用して簡単にオリジナルサイズの表示や保存を行うこともできます。
その機能だけでも色々な拡張機能がありますので、Googleやストアで検索して好みのものをインストールしましょう。
ただし、中にはマルウェア的な拡張機能もあったりするので、オープンソースのものや開発者の情報が明記されているものを選ぶと、比較的安全です。
余談
画像URLの「name」パラメータについては「orig」の他に、「thumb」、「small」、「medium」、「large」、「4096x4096」等があるようです。
また、画像URLの「?format=jpg」を「?format=png」と変えることでPNG画像を表示することができます。
ただし、画質はJPEG画像と同等だと思います(未検証)
これは仕様変更前に画像URLを「.jpg」から「.png」に変えた時の挙動と同じですね。
オリジナル画像を表示できるクライアント(宣伝)
拙作のAndroid用Twitterアプリ『Lagopus』では、画像のオリジナルサイズ表示、保存に対応しています。
その他、自動更新(疑似User Streams)やマルチアカウント等の機能もあります。
よければお試しください。
無料版
play.google.com
有料版
play.google.com
[Android 9] 画面右下の画面回転ボタンを非表示にする
Android 9 Pieで、ナビゲーションバー等に表示される画面回転ボタンを表示させないようにして無効化する方法を紹介します。
いずれの方法もroot化は不要です。
adbコマンドで設定する方法
1. PCでadbコマンドを使える状態にする
PCでadbコマンドを使える状態にします。
こちらのやり方は長くなるので各自調べてね。
2. Android側で『開発者向けオプション』を表示
Android側で開発者向けオプションを表示します(既に表示している場合は手順3へ)。
『設定』アプリから [端末情報] を開き、 [ビルド番号] を7回連続でタップしてください。
『これで開発者になりました!』の通知とともに [開発者向けオプション] が解放されます。


4. adbコマンドを実行
PCとAndroid端末をUSB接続します。
PCでコマンドライン(Windowsなら『コマンド プロンプト』等)を起動し、以下のコマンドを実行します。
adb shell settings put secure show_rotation_suggestions 0
以上で、回転ボタンが表示されなくなるはずです。
Tips. 設定を元に戻す方法
設定を元に戻す(画面回転ボタンを表示する)場合は、上記の手順4のコマンドの代わりに以下のコマンドを実行します。
adb shell settings put secure show_rotation_suggestions 1
画面制御アプリを使う方法
1. 『Rotation Control』をインストール
Google Play ストアより『Rotation Control』をインストールします。
play.google.com
2. Rotation Controlを起動、開始
Rotation Controlを起動し、回転制御開始をオンにします。
それ以外の設定を任意で行います。


3. 通知領域から設定
手順2で回転制御開始をオンにすると、通知領域にウィジェットが表示されます。
ウィジェットの左側にある盾のようなアイコンを選択します。
また、他のアイコンより画面制御モードを設定します。


以上で、回転ボタンが表示されなくなるはずです。
Tips. 『Rotation Controlが他のアプリの上に表示されています』と通知が出る場合
手順3で盾のようなアイコンを選択したタイミングで、『Rotation Controlが他のアプリの上に表示されています』と削除できない通知が表示される場合があります。
この通知が不要な場合、その通知を長押しし、『通知を表示しない』を選択してください。


宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com
[Twitter] PNG画像の投稿方法が変わりました (2019)
Twitterにて2019年2月11日(タイムゾーン不明)に、PNG画像の投稿に関する仕様変更がありました。
変更後の仕様
上から順に判定されるイメージです。
- 3MB以上はJPEGで投稿される
- PNG8はPNGで投稿される
- 長辺900px以下はPNGで投稿される
- 上記以外は一旦品質85%のJPEGに変換され、変換前と変換後でファイルサイズの小さい方が投稿される
(ファイルサイズがちょうど3MBな画像の扱いはよくわかんないです)
図解
フローチャートにしてみました。
Q&A
つまりどういうことだってばよ
画質に関して言えば、どうやって投稿するにしても一長一短あるので、特にこだわらない方は気にする必要は無いです。
こだわる人はがんばって理解して!
PNG8ってなに?
簡単に言うと、色数の少ないPNG画像のことです。
JPEGやPNG24が約1677万色表現できるのに対して、PNG8はわずか256色です。
写真にはまず向いていません。
また、イラストも種類によっては向かない場合があるので、普段投稿するイラストで一度比較テストをしてみるといいかもしれません。
仕様変更前はどうだったの?
仕様変更前の条件は、「3MB以下(未満?)で且つ透過部分を含むこと」でした。
画像の1pxを1%以上透過させて投稿するのが主流だったと思います。
仕様変更前のように1px透過させる必要はあるの?
必要なくなりました。
半透明部分のあるPNG画像を投稿したい
画像1枚のファイルサイズを3MB未満にしたうえで、長辺を900px以下にして投稿すると確実です。
透明部分のあるPNG画像を投稿したい
画像1枚のファイルサイズを3MB未満にしたうえで、長辺を900px以下にするかPNG8にして投稿すると確実です。
85%JPEG変換後よりサイズが小さいことってある?
ほぼないです。単色が画像の大部分を占めるような場合はあり得ます。
『サーバー内部のエラー』とメッセージが出て投稿できない
このエラーは仕様変更前と変更後ともに確認しましたが、具体的な条件は不明です。
少なくとも画像サイズ(いわゆる解像度)を小さくすることによって対応できます。
上記の通りに投稿してもPNGにならない
AndroidやiOSのTwitter公式アプリではすべてのPNGがJPEGで投稿されます。
その場合、ブラウザにてTwitterのサイトから投稿するか、他のPNG画像を投稿できるクライアントから投稿してください。
PNG画像を投稿できるクライアントは?
- twitter.com
- mobile.twitter.com
- tweetdeck.twitter.com
- Tweetdeck for Mac
- Twitter API
- Twitter APIを利用しているサードパーティー製Twitterクライアント
- Twitter for Windows
ソースは?
以下は、Twitter社の方による仕様変更についての説明です。
Upcoming changes to PNG image support
https://twittercommunity.com/t/upcoming-changes-to-png-image-support/118695
Here's a visual aid in how PNG will work on Twitter starting February 11th
— Nolan O'Brien (@NolanOBrien) 2019年1月4日
- PNG will be converted to JPEG 85% quality and tested: Twitter keeps smaller of the PNG and JPEG
- PNGs less than 900 pixels in the longest dimension will be kept
- PNG8 images will be kept pic.twitter.com/GizhhR3xAd
質問がある
コメントください。
この記事に間違いがある
コメントください。
宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com
[Android] PreferenceFragmentCompatで設定画面を作る
AppCompatActivity + PreferenceFragmentCompatで作る設定画面のサンプルコードです。
完成図
今回扱う内容は
- Fragmentの遷移
- 例としてListPreferenceの定義と適用
です。
コード
詳しいことはコード内のコメントに書きましたので参照ください。
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Buttonクリックで設定画面へ findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, SettingsActivity.class)); } }); } @Override protected void onStart() { super.onStart(); // レイアウトルートの背景をテーマ設定の値によって変更 RelativeLayout root = findViewById(R.id.root); SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); switch (defaultSharedPreferences.getString("preference_theme", getString(R.string.default_value_preference_theme))) { case "light": root.setBackgroundColor(Color.parseColor("#FFFFFF")); break; case "dark": root.setBackgroundColor(Color.parseColor("#000000")); break; } } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hatenablog.mnoqlo.sampleapplication.MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:gravity="center" android:text="設定画面を開く" /> </RelativeLayout>
SettingsActivity.java
public class SettingsActivity extends AppCompatActivity implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_settings); // Toolbarの設定 Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); // savedInstanceStateがnullでない場合は前回のFragmentが自動で復元されるのでnullの場合のみ処理 if (savedInstanceState == null) { // トップ画面のFragmentを表示 getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, SettingsFragment.newInstance("preference_root")) .commit(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { // ActionBarの矢印がクリックされたとき、Backボタンと同等の処理をする // 前のFragmentに戻るのではなくActivity自体を終了させたい場合は代わりに finish(); onBackPressed(); return true; } return super.onOptionsItemSelected(item); } // PreferenceScreenがクリックされた時に呼び出されます @Override public boolean onPreferenceStartScreen(PreferenceFragmentCompat caller, PreferenceScreen pref) { // Fragmentの切り替えと、addToBackStackで戻るボタンを押した時に前のFragmentに戻るようにする getSupportFragmentManager() .beginTransaction() .replace(R.id.fragment_container, SettingsFragment.newInstance(pref.getKey())) .addToBackStack(null) .commit(); return true; } }
activity_settings.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hatenablog.mnoqlo.sampleapplication.SettingsActivity"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:theme="@style/ToolbarTheme" /> <FrameLayout android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/toolbar" /> </RelativeLayout>
SettingsFragment.java
public class SettingsFragment extends PreferenceFragmentCompat { public static SettingsFragment newInstance(String rootKey) { SettingsFragment fragment = new SettingsFragment(); Bundle bundle = new Bundle(); // 第1引数をPreferenceFragmentCompat.ARG_PREFERENCE_ROOTとすることでonCreatePreferencesの第2引数がここでputしたrootKeyになります bundle.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, rootKey); fragment.setArguments(bundle); return fragment; } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.preferences, rootKey); // クリックされたPreferenceScreen毎にPreferenceのカスタマイズなど switch (rootKey) { case "preference_appearance": onCreateAppearancePreferences(); break; case "preference_others": break; } } private void onCreateAppearancePreferences() { // テーマ設定の現在の値をSummaryに表示 ListPreference themePreference = (ListPreference) findPreference("preference_theme"); themePreference.setSummary(themePreference.getEntry()); themePreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { int indexOfValue = themePreference.findIndexOfValue(String.valueOf(newValue)); themePreference.setSummary(indexOfValue >= 0 ? themePreference.getEntries()[indexOfValue] : null); return true; } }); } @Override public void onResume() { super.onResume(); // ActionBarのタイトルに現在表示中のPreferenceScreenのタイトルをセット String rootKey = getArguments().getString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT); getActivity().setTitle(findPreference(rootKey).getTitle()); } }
preferences.xml
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="設定" android:key="preference_root"> <PreferenceScreen android:title="外観設定" android:key="preference_appearance"> <ListPreference android:title="テーマ" android:key="preference_theme" android:entries="@array/entries_preference_theme" android:entryValues="@array/entry_values_preference_theme" android:defaultValue="@string/default_value_preference_theme" /> </PreferenceScreen> <PreferenceScreen android:title="その他の設定" android:key="preference_others"> <PreferenceScreen /> </PreferenceScreen> </PreferenceScreen>
arrays.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="entries_preference_theme"> <item>ライト</item> <item>ダーク</item> </string-array> <string-array name="entry_values_preference_theme"> <item>light</item> <item>dark</item> </string-array> </resources>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Sample Application</string> <string name="default_value_preference_theme">light</string> </resources>
styles.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar"> <item name="android:background">@color/colorPrimary</item> </style> </resources>
build.gradle
/* 省略 */ dependencies { implementation 'androidx.preference:preference:最新バージョン' // 試してはいませんが、AndroidXではなくSupport Libraryの場合は implementation 'com.android.support:preference-v14:最新バージョン' }
androidxの方のバージョンはたぶんここ
Support Libraryの方のバージョンはたぶんここ
間違い等ありましたら、コメントしてくださると助かります🙏🙏
宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com
[Android] RecyclerViewのスクロール直後にクリックが動作しない
事象
CoordinatorLayout + AppBarLayout + RecyclerViewのようなレイアウトにおいて、RecyclerViewを端までスクロールさせた際、直後数秒間1回目のタップが動作しない不具合が発生しました。
原因
コンポーネント自体の不具合のようです。
AOSP issue 66996774
解決策
方法1
Support Libraryのバージョン 27.0.1 で修正されたとのアナウンスがありました(https://developer.android.com/topic/libraries/support-library/revisions#27-0-1)
が、アップデートしても改善されないとの声が多くあります。
一応build.gradleよりアップデートを試してみて、改善されない場合は以下の方法をお試しください。
方法2
以下のリンク先のようにAppBarLayout.Behaviorを修正する方法です。基本的にはこちらで対応してください。
Fixed AppBarLayout.Behavior for https://issuetracker.google.com/66996774 · GitHub
方法3
ほとんど方法2と変わりませんが、以下のようにAppBarLayoutを拡張してもいいかもしれません(推奨はしません)。
FixedAppBarLayout.java
public class FixedAppBarLayout extends AppBarLayout { public FixedAppBarLayout(Context context) { super(context, null); } public FixedAppBarLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void setLayoutParams(ViewGroup.LayoutParams params) { if (params instanceof CoordinatorLayout.LayoutParams) { ((CoordinatorLayout.LayoutParams) params).setBehavior(new FixedAppBarLayoutBehavior()); } super.setLayoutParams(params); } // 以下、方法2と同じ public static class FixedAppBarLayoutBehavior extends AppBarLayout.Behavior { public FixedAppBarLayoutBehavior() { super(); } public FixedAppBarLayoutBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); stopNestedScrollIfNeeded(dyUnconsumed, child, target, type); } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); stopNestedScrollIfNeeded(dy, child, target, type); } private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) { if (type == ViewCompat.TYPE_NON_TOUCH) { final int currOffset = getTopAndBottomOffset(); if ((dy < 0 && currOffset == 0) || (dy > 0 && currOffset == -child.getTotalScrollRange())) { ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH); } } } } }
layout.xml
<パッケージ.FixedAppBarLayout android:layout_height="..." android:layout_width="...">
宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com
[Twitter] 6種類のアイコンサイズについて
Twitterのアイコン(プロフィール画像)には6種類のサイズがあります。
サイズ | 解像度 | URL例 |
---|---|---|
mini | 24x24 | https://pbs.twimg.com/profile_images/000/XXXXXXXX_mini.jpg https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg_mini |
normal | 48x48 | https://pbs.twimg.com/profile_images/000/XXXXXXXX_normal.jpg https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg_normal |
bigger | 73x73 | https://pbs.twimg.com/profile_images/000/XXXXXXXX_bigger.jpg https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg_bigger |
200x200 | 200x200 | https://pbs.twimg.com/profile_images/000/XXXXXXXX_200x200.jpg https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg_200x200 |
400x400 | 400x400 | https://pbs.twimg.com/profile_images/000/XXXXXXXX_400x400.jpg https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg_400x400 |
original | 512x512 | https://pbs.twimg.com/profile_images/000/XXXXXXXX.jpg |
解像度は元画像の解像度によって異なる場合があるので注意です。
それと、以前originalサイズで画像の取得自体できないユーザーがいたので、自動化する場合は例外処理をしましょう。
宣伝
Android用Twitterアプリを公開中です。
自動更新(疑似User Streams)やマルチアカウント等の機能に対応しています。
よければお試しください。
無料版
play.google.com
有料版
play.google.com