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

android OS & iPadOS の記録。

基礎。RecyclerView の続き。直線配置、単純クリック処理。

2021-10-17 22:03:03 | Android studio 日記

RecyclerView で複数選択など複雑操作するのに recyclerview-selection を利用します。理解が大変。
で、色々と調べたところ、onClickListener() を紐付けるというか縫い付けるというか…。

単純にonClickListener() を組み付けるとアダプタークラスの中でしか、onClick() が呼ばれない。
MainActivity で onClick() の処理をさせる為には、

MainActivity で onClick() 処理をさせるonClickListenerを用意する。
アダプタークラスにMainActivity で用意したonClickListener を保存するListenerを準備。
MainActivityのListenerを受け取るメソッドを作り、受け取ったListenerを保存。
ViewHolder にデータの他にLayoutViewを設定。
そのLayoutViewに setOnClickListener() で onClick() を組み付ける。
onClick() の中で、保存してある MainActivity の Listener.onClick() を実行。

これでアダプタークラスで発生するクリックイベントがメインアクティビティーに伝搬した。
自力では解決できなかった。imageview にMainActivity で用意したonClickListenerを組み付けたりしたけど上手く動かず、最小セットのLinearLayout にonClickListenerを設定するのは分からなかった。

 

【MainActivity.java】抜粋

        RecyclerView.LayoutManager rLayoutManager = new LinearLayoutManager(this, RecyclerView.HORIZONTAL, true );
        mRecyclerView = findViewById( R.id.recyclerview );
        mRecyclerView.setLayoutManager( rLayoutManager );

        List< String> aPaths = mFolderItemList.getAbsolutePathList();
        List< String> fNames = mFolderItemList.getNameList();

        MyAdapter adapter = new MyAdapter(this, aPaths, fNames );
        mRecyclerView.setAdapter( adapter );
        adapter.setOnItemClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int index = v.getId(); // バインド時にposition と Id は同期している
                String path = aPaths.get( index ); // フルパス名を取得できる
                // 処理を書く
             }
        });

 

【MyAdapter.java】

public class MyAdapter extends RecyclerView.Adapter< MyAdapter.ViewHolder> {

    private Context mContext;
    private LayoutInflater mInflater;
    private RecyclerView mRecyclerView;
    private final List< String> iImagePaths;
    private final List< String> iNames;

    private View.OnClickListener listener; // MainActivityのOnClickListenerを保存

    public MyAdapter( Context context) {
        mContext = context;
        mInflater = LayoutInflater.from( context );
        iImagePaths = new ArrayList<>();
        iNames = new ArrayList<>();
    }
    public MyAdapter( Context context, List< String> itemImagePaths, List< String> itemNames ) {
        mContext = context;
        mInflater = LayoutInflater.from( context );
        iImagePaths = itemImagePaths;
        iNames = itemNames;
    }
    @Override
    public void onAttachedToRecyclerView( @NonNull RecyclerView recyclerView ) {
        super.onAttachedToRecyclerView( recyclerView );
        mRecyclerView = recyclerView;
    }
    @Override
    public void onDetachedFromRecyclerView( @NonNull RecyclerView recyclerView ) {
        mRecyclerView = null;
        super.onDetachedFromRecyclerView( recyclerView );
    }
    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = mInflater.inflate( R.layout.recyclerview, parent, false );
        return new ViewHolder( view );
    }
    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        if ( iImagePaths != null ) {
            Bitmap bitmap = loadImage(iImagePaths.get(position));
            if (bitmap != null) holder.imageView.setImageBitmap(bitmap);
        }
        if ( iNames != null ) holder.textView.setText(iNames.get(position));

        holder.linearLayout.setId( holder.getAdapterPosition() ); // view.getId() で利用
        holder.linearLayout.setOnClickListener( new View.OnClickListener() { // バインド時に設定
            @Override
            public void onClick(View v) {
                listener.onClick(v); // MainActivity の onClick() を呼ぶ
            }
        });
    }
    public void setOnItemClickListener( View.OnClickListener listener ) { // MainActivity と繋ぐパイプ
        this.listener = listener;
    }

    public Bitmap loadImage( String fName ) {
        File file = new File( fName );
        if ( !file.exists() || !file.isFile() ) return null;
        Bitmap scaleBitmap = null;
        try {
            InputStream istream = new FileInputStream( file );
            Bitmap bitmap = BitmapFactory.decodeStream(istream);
            float mag = 160f / (float) bitmap.getHeight();
            int width = (int) ((float) bitmap.getWidth() * mag );
            int height = (int) ((float) bitmap.getHeight() * mag );
            scaleBitmap = Bitmap.createScaledBitmap( bitmap, width, height, true);
            bitmap.recycle();
            istream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return scaleBitmap;
    }
    @Override
    public int getItemCount() {
        return iNames.size();
    }
    public String getAbsolutePath( int position ) {
        if ( position < 0 || position >= iImagePaths.size() ) return null;
        return iImagePaths.get( position );
    }
    public void addAll( List< String> itemImagePaths, List< String> itemNames ) {
        this.iImagePaths.addAll( itemImagePaths );
        this.iNames.addAll( itemNames );
        notifyDataSetChanged();
    }
    public void clear() {
        iImagePaths.clear();
        iNames.clear();
        listener = null;
        mRecyclerView = null;
    }
    static class ViewHolder extends RecyclerView.ViewHolder {
        final LinearLayout linearLayout; // 最小セットごとに View.setOnClickListener() を設定するため
        final ImageView imageView;
        final TextView textView;

        ViewHolder(View v) {
            super(v);
            linearLayout = ( LinearLayout ) v.findViewById( R.id.Linear_layout );
            imageView = v.findViewById( R.id.imageview );
            textView = v.findViewById( R.id.textview );
        }
    }
}

【recyclerview.xml】

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/Linear_layout" // 追加
    略

</LinearLayout>

 

次は、RecyclerViewのスクロール開始オフセットについてかな。中央からスタートさせたい。