質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.99%

  • Android

    5862questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

(Android)アプリの戻るボタンを押したら前の画面に戻る様にしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 255

komon4242

score 5

Android Studio 2.3でストレージ内のファイルをリストビューに表示するアプリを作りました。
以下の方法で取りあえず表示は出来たのですが、アプリの戻るボタンを押すとアプリが終了してしまいます。

望む動きとしては、フォルダの下層部に居る時は戻るボタンで上位層に戻って、
トップに戻った時に「アプリの戻るボタンを押す」とアプリが終了すると言う仕組みにしたいのですがどうしたらよいでしょうか?

googleやteratailで検索して調べようにも「Android 戻るボタン アプリ終了させない」などで調べても望む情報が得られません。
検索キーワードだけでも結構ですので教えて頂けませんでしょうか?

/* import 省略 */

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private ListView listView;
    private CustomAdapter adapter;

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

        // リスト項目が選択された時のイベントを追加
        listView = (ListView) findViewById(R.id.list_item);
        listView.setOnItemClickListener(this);

        // ファイルパスを取得
        String path = Environment.getExternalStorageDirectory().getPath();
        fill(new File(path));
    }

    // アクティビティ内の表示内容構築
    private void fill(File fileDirectory) {
        // タイトル
        setTitle(fileDirectory.getAbsolutePath());

        readLocalStrage(fileDirectory.getPath());

        // ファイルリスト
        File[] aFile = fileDirectory.listFiles();
        List<String> listString = new ArrayList<>();
        if (aFile != null) {
            for (File fileTemp : aFile) {
                listString.add(new aFile.getName());
            }
        }

        // 親フォルダに戻るパスの追加
        if (fileDirectory.getParent() != null) {
            listString.add(0, new String("..", new File(fileDirectory.getParent())));
        }

        // リストビューに表示
        adapter = new CustomAdapter(this, listString);
        listView.setAdapter(adapter);
    }

    // リストをクリックした時の動作
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {

        String String = adapter.getItem(pos);
        if (String.getFile().isDirectory()) {

            fill(String.getFile());
        }
    }
/* import省略 */

// リストビューのアダプタクラス
public class CustomAdapter extends BaseAdapter {

    private List<String> list;

    LayoutInflater inflate;

    public CustomAdapter(Context context, List<String> list){
        this.list = list;
        inflate = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mContentResolver = context.getContentResolver();
    }


    @Override
    public int getCount() {
        return list.size();
    }

    // Objectを明示的に指定するとキャスト不要
   @Override
   public String getItem(int pos) {
        return list.get(pos);
    }

    @Override
    public long getItemId(int pos) {
        return pos;
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup parent) {
        ViewHolder holder;

        // 再利用できるViewがあるかどうか?
        if(convertView == null){
            convertView = inflate.inflate(R.layout.detail_layout, parent, false);

            holder = new ViewHolder();
            holder.icon = (ImageView) convertView.findViewById(R.id.imageView);
            holder.name = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

        String item = getItem(pos);

        if( item.getFile().isDirectory() )
        { // ディレクトリの場合は、名前の後ろに「/」を付ける
            holder.name.setText( item.getName() + "/" );
        }else {

            // ディレクトリじゃないじゃない場合
            holder.name.setText(item.getName());
        }
        return convertView;
    }

    static class ViewHolder {
        ImageView icon;
        TextView name;
    }
}

onBackPressed()を使った方法で修正してみました。

/* import 省略 */

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

    private ListView listView;
    private CustomAdapter adapter;

    private String lastPath;    // 追加
    private String parentPath;    // 追加


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

        // リスト項目が選択された時のイベントを追加
        listView = (ListView) findViewById(R.id.list_item);
        listView.setOnItemClickListener(this);

        // ファイルパスを取得
        String path = Environment.getExternalStorageDirectory().getPath();
        lastPath = Environment.getExternalStorageDirectory().getParent();    // 追加
        fill(new File(path));
    }

    // アクティビティ内の表示内容構築
    private void fill(File fileDirectory) {
        // タイトル
        setTitle(fileDirectory.getAbsolutePath());

        readLocalStrage(fileDirectory.getPath());

        // ファイルリスト
        File[] aFile = fileDirectory.listFiles();
        List<String> listString = new ArrayList<>();
        if (aFile != null) {
            for (File fileTemp : aFile) {
                listString.add(new aFile.getName());
            }
        }

        parentPath = fileDirectory.getParent();    // 追加
        // 親フォルダに戻るパスの追加
        if (fileDirectory.getParent() != null) {
            listString.add(0, new String("..", new File(fileDirectory.getParent())));
        }

        // リストビューに表示
        adapter = new CustomAdapter(this, listString);
        listView.setAdapter(adapter);
    }

    // リストをクリックした時の動作
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {

        String String = adapter.getItem(pos);
        if (String.getFile().isDirectory()) {

            fill(String.getFile());
        }
    }

    // 追加
    @Override
    public void onBackPressed(){
        if(parentPath.equals(lastPath)){
            // トップなら終了
            super.onBackPressed();
        }else {
            fill(new File(parentPath));
        }

    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

Activity#onBackPressedでバックキーのタップを検知してください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/19 15:29

    ありがとうございます。
    onBackPressedで戻るボタンを押した時の処理を追加すると勝手に落ちる事はなくなりました。
    ですが処理的には少し難しくなりました。
    具体的に言いますと、戻るボタンを押した時の自分の階層がわからないのです。

    取りあえずfill()にold_pathを追加してバックボタンを押した時にold_pathがトップ(/storage/emulated/0)と同じ場合は処理を終了すると言う処理で何とかなりそうです。ありがとございました

    キャンセル

  • 2017/10/19 20:44

    解決していると思われるので、ベストアンサーにして解決済にしてください

    キャンセル

+1

MainActivityの中身を変更するのではなく、
新しいMainActivityを上に重ねていく形にするのはどうでしょうか。

MainActivityのonCreateでIntentを確認して、
パスが入っていたら、外部ストレージパスの代わりに指定されたパスのリストを表示する。
階層潜るときはIntentにパスを詰めて新しいMainActivityをスタートする。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/19 15:25

    それはFragmentと言うやつでしょうか?(ごめんなさいよく分かってないです)
    Activityを重ねれば最後のアクティビティまでアプリが終了される事は無いですね。

    キャンセル

  • 2017/10/19 15:57

    いいえ、普通のActivityで出来るはずです。
    ちょっと短絡的すぎたかなって感じもしてます。

    ツールバーとか付け加えてファイルコピーとかするのであれば、
    Fragmentでやったほうがいいんだろうなぁ・・・

    Fragment使うならyonaさん案のonBackPressedを使うことになると思います。
    FragmentManagerのBackStackを利用したら案外簡単に実装できるのかなって感じがします。
    (私自身Fragmentあまり使ったことないので何も言えないです。)

    キャンセル

  • 2017/10/20 08:55

    回答ありがとうございます。
    実装出来たyanaさんの方をベストアンサーにしましたが、
    abs123さんの解決方も対応してみます。

    あの後機能を追加したらまたエラーが出たので再度別件で質問するかもしれません。
    その時はまた助言してください。

    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Android

    5862questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。