勘違いでImageViewの画像サイズ取得値が間違っていた。Margin設定で複雑に考えていた。これらを正規値を取得、Padding設定でシンプル変更に変えたところ満足する内容になった。
デバイスサイズより画像サイズが小さい時に余白部分を計算して、半分ずつPadding設定。
Bitmap mBitmap = BitmapFactory.decodeStream(istream); // ビットマップへデコード
if (mBitmap != null) {
mView.setImageBitmap( mBitmap ); // イメージビューにビットマップ登録
int dx = mBitmap.getWidth();
if ( dx < displayWidth ) {
dx = ( displayWidth - dx ) / 2; // 余白の半分
} else dx = 0; // サイズが大きい時は余白0
int dy = mBitmap.getHeight();
if ( dy < displayHeight ) {
dy = ( displayHeight - dy ) / 2;
} else dy = 0;
mView.setPaddingRelative( dx, dy, dx, dy ); // イメージビューにパディング設定
}
ビュースイッチャーを使い、フルスクロールの下にイメージビューがある。そして、画面サイズより小さい画像を中央に表示したい場合は、プログラムで Padding設定をする。
プログラム =========================================================
【 FullscreenActivity.java 】
public class FullscreenActivity extends AppCompatActivity {
private int displayWidth, displayHeight; // デバイスのサイズ
private int targetIndexNo; // ファイル名リスト配列のインデックスNO
// ファイル名リスト配列。カスタムソート用
private final ArrayList< MyNumbersInString> mFileNameList = new ArrayList< >();
private boolean viewFlag; // ビュースイッチャー用
private ViewSwitcher mViewSwitcher; // ビュースイッチャー
private MyScrollView mMSV1, mMSV2; // ビュースイッチャー設定用
private ImageView imageView1, imageView2; // レイアウト組み込みイメージビュー
// シンプルタッチイベント用
private GestureDetectorCompat mDetector;
private final MyGestureListener mGestureListener = new MyGestureListener();
private AssetManager mAssetManager; // assetsフォルダアクセス
// ******************************************************************
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // OSによりデバイスサイズの求め方が違う
WindowMetrics mWindowMetrics = this.getWindowManager().getCurrentWindowMetrics();
displayWidth = mWindowMetrics.getBounds().width();
displayHeight = mWindowMetrics.getBounds().height();
} else {
WindowManager mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
Display mDisplay = mWindowManager.getDefaultDisplay();
Point mRealSize = new Point();
mDisplay.getRealSize(mRealSize);
displayWidth = mRealSize.x;
displayHeight = mRealSize.y;
}
// ビュースイッチャー登録準備
mMSV1 = (MyScrollView) getLayoutInflater().inflate(R.layout.image1, null);
mMSV2 = (MyScrollView) getLayoutInflater().inflate(R.layout.image2, null);
// スイッチャー設定
mViewSwitcher = (ViewSwitcher) findViewById( R.id.viewSwither );
mViewSwitcher.addView( mMSV1, 0 );
mViewSwitcher.addView( mMSV2, 1 );
// 切り替え時のアニメーション
mViewSwitcher.setInAnimation(AnimationUtils.loadAnimation( this, android.R.anim.fade_in));
mViewSwitcher.setOutAnimation(AnimationUtils.loadAnimation( this, android.R.anim.fade_out));
// イメージのレイアウト情報設定。ビットマップは後で設定
imageView1 = findViewById(R.id.image_view1);
imageView2 = findViewById(R.id.image_view2);
// assetsフォルダ情報登録
mAssetManager = getResources().getAssets();
// フルスクリーン表示 ------------------
View decorView = getWindow().getDecorView();
int uiOptions;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION ;
} else {
uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE ;
}
decorView.setSystemUiVisibility(uiOptions);
// ---------------------------------------
// 本来、ディレクトリ絶対パスを渡す。画像ファイル名をリストアップ
setFileNameList( mAssetManager );
viewFlag = true; // 初期化
targetIndexNo = 0;
// イメージビューにビットマップを設定。本来はフルパスを渡す
setImage( imageView1, "image/" + mFileNameList.get(0).getName() );
setImage( imageView2, "image/" + mFileNameList.get(1).getName() );
// シンプルタップ処理設定
mViewSwitcher.setOnTouchListener( MyTouchEventListener );
mDetector = new GestureDetectorCompat(this, mGestureListener );
mDetector.setOnDoubleTapListener( mGestureListener );
}
// タッチイベントのディスパッチ設定
@Override
public boolean dispatchTouchEvent( MotionEvent event ) {
super.dispatchTouchEvent(event);
mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
private final View.OnTouchListener MyTouchEventListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
};
// とりあえず、ダブルタップがシングルタップに飛び込まないように
private boolean doubleTapFlag = false;
// シンプルタップ、オーバーライド
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if( !doubleTapFlag ) { // ダブルタップでない
if ( (int) e.getRawX() > ( displayWidth / 2 ) ) { // 画面の右側タップ
if ( ++targetIndexNo >= mFileNameList.size() ) { // indexをインクリメント
targetIndexNo = 0;
}
if ( viewFlag ) { // image1が表示されているので image2にセット
setImage( imageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
viewFlag = false; // image2 表示フラグセット
} else {
setImage( imageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
viewFlag = true;
}
mViewSwitcher.showNext(); // 次を表示
} else {
if ( --targetIndexNo < 0 ) {
targetIndexNo = mFileNameList.size() - 1;
}
if ( viewFlag ) { // image1が表示されているので image2にセット
setImage( imageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
viewFlag = false;
} else {
setImage( imageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
viewFlag = true;
}
mViewSwitcher.showPrevious(); // 前を表示
}
}
doubleTapFlag = false; // リセット
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
doubleTapFlag = true; // セット。return true; でもいいのかな・・
return false;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
doubleTapFlag = false; // リセット
return false;
}
};
// ファイル名リストアップ。
private void setFileNameList( AssetManager am ) {
String fName;
String[] mList = new String[0];
try {
mList = am.list("image"); // 本来はディレクトリ絶対パスからリストアップ
} catch (IOException e) {
e.printStackTrace();
}
for (String s : mList) {
fName = s;
fName.toLowerCase(); // 小文字に変換
if ( fName.endsWith(".jpg") || fName.endsWith(".png")) { // 画像ファイル選択
mFileNameList.add( new MyNumbersInString(s) ); // リスト配列へ
}
}
Collections.sort( // 配列ソート
mFileNameList, new Comparator< MyNumbersInString>() {
@Override
public int compare(MyNumbersInString mn1, MyNumbersInString mn2) {
return mn1.getName2().compareTo( mn2.getName2() );
}
}
);
}
// イメージビューにビットマップ登録
private void setImage( ImageView iView, String fName ) {
try {
InputStream istream = mAssetManager.open(fName); // ストリームを開く
Bitmap mBitmap = BitmapFactory.decodeStream(istream); // ビットマップへデコード
if (mBitmap != null) {
iView.setImageBitmap( mBitmap ); // イメージビューにビットマップ登録
int dx = mBitmap.getWidth();
if ( dx < displayWidth ) {<br /> dx = ( displayWidth - dx ) / 2;
} else dx = 0;
int dy = mBitmap.getHeight();
if ( dy < displayHeight ) {<br /> dy = ( displayHeight - dy ) / 2;
} else dy = 0;
iView.setPaddingRelative(dx,dy,dx,dy); // イメージビューにパディング設定
}
istream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
【 MyNumbersInString.java 】
public class MyNumbersInString {
private String name1 = ""; // 元のファイル名
private String name2 = ""; // 漢字、数字混在のとき、半角数字を前方を"0"で埋めた8桁に修正
/*
ArrayList<> で、ファイル名をソートするための準備。name2を判定条件に使う
**/
public MyNumbersInString( String name ){
name1 = name;
StringBuilder sb = new StringBuilder(name);
String[] msplit1 = sb.toString().split( "[^\\d]" ); // 数字以外で分割
String[] msplit2 = sb.toString().split( "\\d" ); // 数字で分割
boolean mFlag = true;
sb = new StringBuilder();
// 1つの文字列を同条件反転分割しているので[0]のみ、どちらか必ず文字が入っている
if (msplit1[0].length() == 0) {
mFlag = true;
sb.append(msplit2[0]); // 文字を積む
}
if (msplit2[0].length() == 0) {
mFlag = false;
sb.append( zeroCompensation( msplit1[0]) ); // 0補填をして数字を積む
}
// 数字の次は文字、文字の次は数字、フラグで切り替え積んでいく。数字は0補填
int i = 0, j = 0, len;
while ( ( i
if (mFlag) { // 直前が数字でなかった
if ( ++i
if (msplit1[i].length() != 0) { // 数字が現れた
sb.append( zeroCompensation( msplit1[i] ) );
mFlag = false;
}
}
} else { // 直前が文字でなかった
if ( ++j
if (msplit2[j].length() != 0) { // 文字が現れた
sb.append(msplit2[j]);
mFlag = true;
}
}
}
}
name2 = sb.toString();
}
public String getName(){
return name1;
}
public String getName2(){
return name2;
}
private String zeroCompensation(String text){
StringBuilder sb = new StringBuilder();
int len = text.length(); // 桁数
if ( len < 8 ) { // 8桁以下なら0を前に付けて8桁に合わせる
len = 8 - len;
for (int c = 0; c
sb.append("0");
}
}
sb.append( text );
return sb.toString();
}
}
【 MyScrollView.java 】
public class MyScrollView extends ScrollView {
public MyScrollView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
}
public MyScrollView(Context context, AttributeSet attrs){
super(context, attrs);
}
public MyScrollView(Context context){
super(context);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept){
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event){
onTouchEvent(event);
return false;
}
}
注意:半角“<”を全角“<”に置換。手抜き。
【 activity_fullscreen.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/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/fullscreenBackgroundColor"
android:theme="@style/ThemeOverlay.MyTest2.FullscreenContainer"
tools:context=".FullscreenActivity">
<ViewSwitcher
android:id="@+id/viewSwither"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
※ ”com.????.mytest2” この部分は各々のパッケージネーム
【 image1.xml 】
<?xml version="1.0" encoding="utf-8"?>
<com.????.mytest2.MyScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/L_Layout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="ObsoleteLayoutParam">
<ImageView
android:id="@+id/image_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription" />
</LinearLayout>
</HorizontalScrollView>
</com.????.mytest2.MyScrollView>
【 image2.xml 】
<?xml version="1.0" encoding="utf-8"?>
<com.????.mytest2.MyScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="@+id/L_Layout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
tools:ignore="ObsoleteLayoutParam">
<ImageView
android:id="@+id/image_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription" />
</LinearLayout>
</HorizontalScrollView>
</com.????.mytest2.MyScrollView>
画像のリアルサイズモード、フィットサイズモード切り替え。設定用アクティビティーの組み込み。色々。
参考文献
Android Studio : ViewSwitcher とフリックによる画面切り替え。
ViewSwitcherで2つのViewをなめらかに切り替える。
【Android】画面タッチイベントを実装する。
【 Android アプリ開発 】全画面表示を行う方法 ( 通知バー非表示 )
Android: 画面サイズよりも大きいViewを縦/横/斜めでスクロールする。