タブレット用プログラムの書き止め

android OS & iPadOS の記録。

startActivityForResult() 別アクティヴィティに偏移

2021-06-29 19:20:57 | Android studio 日記

 躓き続きで何とか別アクティビティーの仮デザインを終わらせてプログラムを組み込んでビルドしたら、マニュフェストファイルでエラー連発。問題部分をremove指示されるから削除してもビルドエラーで止まって再表示すると削除した部分が復活していて、remove指示・・・。どこかミスったな。

 組み込んだ部分を取り外しても元に戻らない。最初からやり直しか。プロジェクトのコピーができれば、途中からできるのに使いづらい。


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

なぜか、ImegeView の scaleType が作動しないので自作

2021-06-25 13:52:58 | Android studio 日記

 画像のリアルサイズモード、フィットサイズモード切り替え。完成ではない。アクションが決まらない。表示だけができた。
 デバイスがポートレート表示(縦長)で画像がランドスケープ表示(横長)だとフィットモードは小さく表示されてしまうので90度回転させる事にした。そこでデバイスを横倒しにしたらどうなるのかエミュレーターで回転。回転直後は画像が乱れてしまったが、画像を進める、戻すでフィット表示になる。
 自動で回転したときにコールバックされるメソッドを追加とオーバーライドする。表示手順は問題なさそうなので、現在の画像をイメージビューに再登録する。

 余談、ImegeView の scaleTypeはレイアウトの組み合わせ、設定方法の間違い、何かしら問題があるのだろう。できるだけ楽をしたいのだが、まぁ仕方ない。苦労も思考の多様性を生むので良しとしなければ・・。でも、あぁ、楽がしたい。

 

 新しい部分だけ注釈挿入。

【 FullscreenActivity.java 】

public class FullscreenActivity extends AppCompatActivity {

    private final int DISPLAY_WIDTH = 0;  // システム上アクティビティーの再起動が起こる
    private final int DISPLAY_HEIGHT = 1; // 必要な時に呼び出す為に必要


    private final ArrayList<MyNumbersInString> mFileNameList = new ArrayList<>();
    private AssetManager mAssetManager;

    private int targetIndexNo;
    private boolean viewFlag, realSizeFlag, pageModeFlag;

    private MyScrollView mMSV1, mMSV2;
    private ImageView imageView1, imageView2;
    private LinearLayout mL_Layout1, mL_Layout2;
    private ViewSwitcher mViewSwitcher;

    private GestureDetectorCompat mDetector;
    private final MyGestureListener mGestureListener = new MyGestureListener();

 

    // ******************************************************************

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fullscreen);

        // 中略 //


        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));

        pageModeFlag = true; // true(1page) false(2page)
        realSizeFlag = false;     // true(real mode) false(fit mode)
        viewFlag = true;          // true(sw0) false(sw1)
        targetIndexNo = 0;

        mAssetManager = getResources().getAssets();
        setFileNameList();

        imageView1 = findViewById(R.id.image_view1); // sw0
        imageView2 = findViewById(R.id.image_view2); // sw1

        setImage( imageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
        setImage( imageView2, "image/" + mFileNameList.get(targetIndexNo).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() > ( getScreenSize(DISPLAY_WIDTH) / 2 ) ) { // デバイスサイズ呼び出し

                    if ( ++targetIndexNo >= mFileNameList.size() ) {
                        targetIndexNo = 0;
                    }
                    if ( viewFlag ) {         // image1が表示されているので image2にセット
                        setImage( imageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
                        viewFlag = false;
                    } 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 false;
        }


        @Override
        public boolean onSingleTapUp(MotionEvent e) {

            doubleTapFlag = false;
            return false;
        }

    };

        // 新設。引数を渡して、現在の幅か高さを戻り値で受け取る
    private int getScreenSize( int mode ) {
        int ret = -1;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {    // OSにより求め方が違う
            WindowMetrics mWindowMetrics = this.getWindowManager().getCurrentWindowMetrics();
            switch ( mode ) {
                case DISPLAY_WIDTH:
                    ret = mWindowMetrics.getBounds().width();
                    break;
                case DISPLAY_HEIGHT:
                    ret = mWindowMetrics.getBounds().height();
                    break;
            }
        } else {
            WindowManager mWindowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
            Display mDisplay = mWindowManager.getDefaultDisplay();
            Point mRealSize = new Point();
            mDisplay.getRealSize(mRealSize);
            switch ( mode ) {
                case DISPLAY_WIDTH:
                    ret = mRealSize.x;
                    break;
                case DISPLAY_HEIGHT:
                    ret = mRealSize.y;
                    break;
            }
        }
        return ret;
    }

    private void setFileNameList() {

        String fName;
        String[] mList = new String[0];
        try {
            mList = mAssetManager.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() {
                    @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 ) {
                if ( realSizeFlag ) {              // real mode
                    iView.setImageBitmap(mBitmap);
                    setPaddingImageView( iView, mBitmap.getWidth(), mBitmap.getHeight() );
                } else {                              // fit mode
                    float f;
                    Bitmap tempBitmap = null;         // 90度回転用作業ビットマップ
                    if ( pageModeFlag ) {                  // one page mode
                        Matrix matrix = new Matrix();  // 回転クラス
                        int sysOri = getOrientation();   // デバイスがポートか、ランドか
                        int iShape = getImageShape( mBitmap.getWidth(), mBitmap.getHeight() ); // 画像がポートか、ランドか
                        if ( ( ( sysOri == Configuration.ORIENTATION_PORTRAIT ) &&                    // システムがポート、画像がランドの時
                                ( iShape == Configuration.ORIENTATION_LANDSCAPE ) )
                        ) {
                            matrix.setRotate(90, mBitmap.getWidth(), mBitmap.getHeight());           // 角度と領域を指定
                        } else if ( ( sysOri == Configuration.ORIENTATION_LANDSCAPE ) &&           // 別の条件の時
                                    ( iShape == Configuration.ORIENTATION_PORTRAIT )
                        ) {
                            matrix.setRotate(270, mBitmap.getWidth(), mBitmap.getHeight());         // 別の角度と領域を指定
                        }
                        if ( sysOri != iShape ) {           // ポート、ランド、双方が違う時に回転する
                            tempBitmap = Bitmap.createBitmap(mBitmap, 0, 0,                               // 元画像を回転
                                    mBitmap.getWidth(), mBitmap.getHeight(), matrix, true);
                            mBitmap.recycle();             // 元々のメモリ領域を回収
                            mBitmap = tempBitmap;     // 作業用のビットマップメモリに参照場所を移す。関数内で確保領域だからリーク少ない?
                        }
                    }
                    f = setImageViewFit(iView, mBitmap.getWidth(), mBitmap.getHeight());        // フィット用の倍率を求める
                    int mWidth = (int)( (float) mBitmap.getWidth() * f );  // 画像サイズの幅か高さをデバイスに合わせる
                    int mHeight =(int)( (float) mBitmap.getHeight() * f );
                    Bitmap scaleBitmap = Bitmap.createScaledBitmap( mBitmap, mWidth, mHeight,true ); // サイズ変更
                    iView.setImageBitmap(scaleBitmap);
                    setPaddingImageView( iView, scaleBitmap.getWidth(), scaleBitmap.getHeight() );        // 余白を設定
                }
            }
            istream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void setPaddingImageView( ImageView iView, int bx, int by ) {

        int displayWidth = getScreenSize(DISPLAY_WIDTH);   // 現在のデバイス幅を取得
        int displayHeight = getScreenSize(DISPLAY_HEIGHT); // 現在のデバイス高さを取得
        int paddingX, paddingY;

        if ( bx < displayWidth ) {
            paddingX = (displayWidth - bx) / 2;
        } else paddingX = 0;
        if ( by < displayHeight ) {
            paddingY = ( displayHeight - by ) / 2;
        } else paddingY = 0;

        iView.setPaddingRelative( paddingX, paddingY, paddingX, paddingY ); // イメージビューに Padding を設定
    }

    private float setImageViewFit( ImageView iView, int bx, int by ) {

        int displayWidth = getScreenSize(DISPLAY_WIDTH);   // 現在のデバイス幅を取得
        int displayHeight = getScreenSize(DISPLAY_HEIGHT); // 現在のデバイス高さを取得

        // デバイスの大きさを画像のサイズで割る意味は、その倍率に画像サイズを掛けるとデバイスのサイズになる
        // 幅、高さの倍率の大きさを比較すると、どっちを基準にするか分かる
        float fX = (float) displayWidth / (float) bx;
        float fY = (float) displayHeight / (float) by;
        float ret = 1f;

        if ( ( ( bx > displayWidth ) && ( by > displayHeight ) )              // 画面サイズより画像サイズが大きい
                || ( ( bx < displayWidth ) && ( by < displayHeight ) ) ) {  // 画面サイズより画像サイズが小さい
            if ( fX > fY ) {
                ret = fY;    // 幅の倍率が大きければ、高さの倍率を基準にする
            } else {
                ret = fX;    // 高さの倍率が大きければ、幅の倍率を基準にする
            }
        } else if ( ( bx > displayWidth ) && ( by < displayHeight ) ){      // 画像の幅を画面の幅に合わせるので
            ret = fX;
        } else if ( ( bx < displayWidth ) && ( by > displayHeight ) ) {     // 画像の高さを画面の高さにに合わせるので
            ret = fY;
        }
        return ret; // 戻す倍率は基準となる1つだけ、幅、高さを掛ければ、どっちかが画面のサイズになる
    }

    public int getOrientation() { // デバイスが、縦か、横持ちか返す

        Resources resources = getResources();
        Configuration config = resources.getConfiguration();

        return config.orientation; // Configuration.ORIENTATION_PORTRAIT
    }

    public int getImageShape( int x, int y ) { // 画像が縦長か、横長か返す
        int ret = 0;
        if ( x > y ) {
            ret = Configuration.ORIENTATION_LANDSCAPE;
        } else {
            ret = Configuration.ORIENTATION_PORTRAIT;
        }
        return ret;
    }

    @Override // 回転されて再描画が起こった。イメージビューを再設定
    public void onConfigurationChanged( Configuration newConfig ) {
        super.onConfigurationChanged(newConfig);

        if ( viewFlag ) {                            // image1が表示されている
            setImage( imageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
        } else {                                       // image2が表示されている
            setImage( imageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
        }
    }

}

 


【activity_fullscrenn.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"

    android:configChanges="orientation|screenSize" <--  ここの部分を書き足し  -->

    tools:context=".FullscreenActivity">


       <ViewSwitcher
           android:id="@+id/viewSwither"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

</RelativeLayout>

 

 

 

参考文献

Android Studio : ViewSwitcher とフリックによる画面切り替え。
ViewSwitcherで2つのViewをなめらかに切り替える。
【Android】画面タッチイベントを実装する。
【 Android アプリ開発 】全画面表示を行う方法 ( 通知バー非表示 )
Android: 画面サイズよりも大きいViewを縦/横/斜めでスクロールする。



  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ViewSwitcher の ImageView の Padding 設定

2021-06-23 17:00:02 | Android studio 日記

 勘違いで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を縦/横/斜めでスクロールする。



 

 

 


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

fullscroll やり直し?

2021-06-22 23:14:03 | Android studio 日記

 デバイスサイズより画像サイズが大きいものだけならそれなりの作動をするが、デバイスサイズより画像サイズが小さいものと混合状態だと表示に異常が発生する。表示サイズ、スクロール領域など。

 自前でスクロール処理を行えば、表示サイズ、表示位置、スクロール領域など明確に制御できます。システムをすべて理解して使うよりは短期間で構築できる。ほぼ理解してからシステムで用意されているものに差し替えれば良いのかな・・。

 ViewSwitcher の階層の場所を変えてどういう作動になるか確認してから作り直し。

 という事で scrollView の下に ViewSwitcher を置いていたものを ViewSwitcher の下にスイッチするビュー毎に ScrollView、LinearLayout、ImageView を xml で用意する。少しの手直しで組み込みは終了。動作は表示サイズ、スクロール領域は思い通りだが、表示位置は左上に固定、グラビティ関連設定では中央に移動できない状態、なにかしら対応する予定。リアルとフィットのモードも模索中。


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ViewSwitcher を使う。

2021-06-21 15:02:22 | Android studio 日記

 【 ViewSwitcher 】 フルスクリーン、フルスクロール、ファイル名リストアップ、タップ処理、ここまでできたのでファイル名のリスト順に画像を切り替えるプログラムにまとめる。
 自前で画像の切り替えをしようと思ったが、イメージスイッチャー、ビュースイッチャーを見つけた。切り替えのアニメーションが揃っていて面白そうなので利用する。全体の動作チェックなのでフェードイン、アウトを使う。設定が楽だから。


 とりあえず、通しで。


【MainActivity.java】

public class MainActivity extends AppCompatActivity {

        // デバイス画面サイズ、Width、Height
    private int displayWidth, displayHeight;

        // Assetsフォルダ操作用
    private AssetManager mAssetManager;
        // ファイル名リスト用index
    private int targetIndexNo;
        // ファイル名リスト、ソート用
    private final ArrayList<MyNumbersInString> mFileNameList = new ArrayList<>();

        // viewswitcher切り替えビュー把握用フラグ
    private boolean viewFlag; 
        // ビュースイッチャー  
    private ViewSwitcher mViewSwitcher;

        // viewswitcher割り当てイメージビュー
    private ImageView mImageView1, mImageView2; 
        // viewswitcher割り当てレイアウト
    private LinearLayout mL_Layout1, mL_Layout2; 

        // シンプルタップアクション取得用
    private GestureDetectorCompat mDetector; 
    private MyGestureListener mGestureListener = new MyGestureListener();

    // ******************************************************************

 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // フルスクリーン表示
        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);

        // OSによりデバイスサイズの求め方が違うらしい 
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            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;
        }

        // ビュースイッチャーに image1.xml image2.xml を設定する
        viewFlag = true;
        LinearLayout mL_Layout1 = (LinearLayout) getLayoutInflater().inflate(R.layout.image1, null);
        LinearLayout mL_Layout2 = (LinearLayout) getLayoutInflater().inflate(R.layout.image2, null);

        mViewSwitcher = (ViewSwitcher) findViewById( R.id.viewSwither );
        mViewSwitcher.addView(mL_Layout1);
        mViewSwitcher.addView(mL_Layout2);

        mViewSwitcher.setInAnimation(AnimationUtils.loadAnimation( this, android.R.anim.fade_in));
        mViewSwitcher.setOutAnimation(AnimationUtils.loadAnimation( this, android.R.anim.fade_out));

        // 画像ファイル差し替え用
        mImageView1 = findViewById(R.id.image_view1);
        mImageView2 = findViewById(R.id.image_view2);

        // Assetsフォルダ操作用
        mAssetManager = getResources().getAssets();

        // Assetsフォルダ内imageフォルダの画像ファイル名をリスト化
        setFileNameList();
        targetIndexNo = 0;

        // ファイル名から画像をイメージビューに設定する
        setImage( mImageView1, "image/" + mFileNameList.get(0).getName() );
        setImage( mImageView2, "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() {
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    };

        // ダブルタップフラグ。onDoubleTap(){return true;}で良いのかも知れない
    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() ) {
                        targetIndexNo = 0;
                    }
                    if ( viewFlag ) { // image1が表示されているので image2にセット
                        setImage( mImageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
                        viewFlag = false; // 表示判定フラグ書き換え
                    } else {
                        setImage( mImageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
                        viewFlag = true;
                    }
                    mViewSwitcher.showNext(); // 次を表示切替え
                } else { // 画面の左側をタップ
                    if ( --targetIndexNo < 0 ) {
                        targetIndexNo = mFileNameList.size() - 1;
                    }
                    if ( viewFlag ) { // image1が表示されているので image2にセット
                        setImage( mImageView2, "image/" + mFileNameList.get(targetIndexNo).getName() );
                        viewFlag = false;
                    } else {
                        setImage( mImageView1, "image/" + mFileNameList.get(targetIndexNo).getName() );
                        viewFlag = true;
                    }
                    mViewSwitcher.showPrevious(); // 前を表示切替え
                }
            }
            doubleTapFlag = false;
            return false;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            doubleTapFlag = true;
            return false;
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            doubleTapFlag = false;
            return false;
        }
    };


        // 画像がデバイス画素数よりはるかに大きい時に縮小してBitmapを返す。
    private Bitmap bitmapDimension(InputStream istream){

    BitmapFactory.Options mOptions = new BitmapFactory.Options();
    mOptions.inJustDecodeBounds = true;
    Bitmap mBitmap = BitmapFactory.decodeStream(istream, null, mOptions);//bitmapは取得されない

    float mX = (float)mOptions.outWidth / (float)displayWidth;;
    float mY = (float)mOptions.outHeight / (float)displayHeight;;

    if( mX >= 8.0 || mY >= 8.0 ){
        mOptions.inSampleSize = 4;
    } else if( mX >= 4.0 || mY >= 4.0 ){
        mOptions.inSampleSize = 2;
    } else mOptions.inSampleSize = 1;

    mOptions.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(istream, null, mOptions);
}

        // "Assets/image" 内のファイル名をリストアップ
    private void setFileNameList() {

        String fName;
        String[] mList = new String[0];
        try {
            mList = mAssetManager.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() {
                    @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 = bitmapDimension(istream);
            if (mBitmap != null) iView.setImageBitmap(mBitmap);
            istream.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

 

※ “<”半角 を “<”全角 に変更しています。半角はhtml文書変換で誤変換されて無表示になる。

【activity_main.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="match_parent"
    android:layout_height="match_parent"
    android:theme="@style/ThemeOverlay.MyTest2.MainContainer" >

    <HorizontalScrollView

        android:id="@+id/H_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"  >

        <ViewSwitcher

            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/viewSwither"
            tools:ignore="ScrollViewSize" />

    </HorizontalScrollView>

</com.????.mytest2.MyScrollView >


 ※ ”com.????.mytest2” この部分は各々のパッケージネーム

 

 スイッチャー設定に使う。

【image1.xml】


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="horizontal">

    <ImageView

        android:id="@+id/image_view1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="full screen mode"
        tools:ignore="HardcodedText" />

</LinearLayout>

 

【image2.xml】

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="horizontal">

    <ImageView

        android:id="@+id/image_view2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="full screen mode"
        tools:ignore="HardcodedText" />

</LinearLayout>

 

 あと、基本的な画像サイズの変更も組み込む。2本の指で画面上を狭めたり広げたりでサイズを変更する。

 ><:画面サイズより画像サイズが大きいとき小さくして画面サイズに合わせる。
    画面サイズより画像サイズが小さいときリアルサイズで表示する。

    <>:画面サイズより画像サイズが大きいときリアルサイズで表示する。
    画面サイズより画像サイズが小さいとき大きくして画面サイズに合わせる。

 タッチアクションで画像切り替えをスライドアニメーションで実行する。

 

参考文献

Android Studio : ViewSwitcher とフリックによる画面切り替え
ViewSwitcherで2つのViewをなめらかに切り替える


  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする