RecyclerView関連

RecyclerViewに関する、レアなセオリー。。。。をいくつか書いてみたいと思います。使い勝手と見た目がそこそこ重要とされる時代になってしまったのです。

notifyItemChangeする際の点滅をおさえました。

import androidx.recyclerview.widget.RecyclerView;
...
    public static void stopAnimator(RecyclerView view) {
        RecyclerView.ItemAnimator animator = view.getItemAnimator();
        if (animator instanceof DefaultItemAnimator) {
            ((DefaultItemAnimator)animator).setSupportsChangeAnimations(false);
        }
    }

ドラッグできる画面を増やしました。1画面の分の実装を添付します。そのままは使えないですが、参考にはなると思います。

ドラッグでレイアウトを修正するケース。
カスタムRecyclerView.Adapterに以下のメソッドを追加しています。

import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
....
    ItemTouchHelper helper = null;
    public void prepareDragAndDrop(RecyclerView attached) {
        // 解除はnullのようでした(Android16までOK)
        prepareHelper().attachToRecyclerView(attached);
    }
    public void swap(int from, int to) {
        _listStatus.add(to, _listStatus.remove(from));
    }
    public CCStatus get(int index) {
        return _listStatus.get(index);
    }
    public void set(int index, CCStatus status) {
        CCStatus keep1 = get(index);
        if (keep1 != null) {
            keep1.getListenerList().removeListener(_myListener);
        }
        listStatus.set(index, status);
        status.getListenerList().addListener(_myListener);
        if (keep1 == _bottomSel) {
            _bottomSel = status;
        }
        if (keep1 == _rightSel) {
            _rightSel = status;
        }
    }
    public int indexOf(CCStatus status) {
        return _listStatus.indexOf(status);
    }
    protected ItemTouchHelper prepareHelper() {
    if (helper != null) {
        return helper;
    }
    helper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
            ItemTouchHelper.UP | ItemTouchHelper.DOWN /*|ItemTouchHelper.START | ItemTouchHelper.END*/, 0
    ) {
        @Override
        public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
            return true;
        }

        @Override
        public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
            //askAndRemove(viewHolder.getAdapterPosition());
        }
    });

    return helper;
}

ドラッグで、アイテムの値を変更するケース

import androidx.recyclerview.widget.RecyclerView;
...
    binding.recyclerButtons.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        int[] _lastPress = new int[16];
        int []_touchX = new int[16];
        int []_touchY = new int[16];
        int[] _originalValue = new int[16];

        @Override
        public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent event) {
            boolean proc = false;
            try {
                MainParameters mainParams = MidiOne.getInstance().getMainParameters();
                 GridLayoutManager layout = (GridLayoutManager) rv.getLayoutManager();
                 for (int seek = 0; seek < event.getPointerCount(); ++seek) {
                     int pointer = event.getPointerId(seek);
                     int x = (int) event.getX(seek);
                     int y = (int) event.getY(seek);
                     int action = event.getActionMasked();
                     String act = Integer.toString(action);
                     if (action == MotionEvent.ACTION_DOWN || action== MotionEvent.ACTION_POINTER_DOWN) {
                        act = "Down";
                        proc = true;
                    }
                    if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_UP) {
                         act = "Up";
                        proc = true;
                    }
                    if (action == MotionEvent.ACTION_MOVE) {
                        act = "Move";
                        proc = true;
                    }
                    if (pointer >= 15) {
                        continue;
                    }
                    int padIndex = -1;

                    for (int i = 0; i < layout.getChildCount(); ++i) {
                        View v = layout.getChildAt(i);
                        Rect rect = new Rect();
                        rect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
                         if (rect.contains((int) x, (int) y)) {
                        //if (rect.contains((int) event.getX(), (int) event.getY())) {
                            padIndex = i;
                        }
                    }
                    if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {
                        if (padIndex >= 0) {
                            if (_lastPress[pointer] >= 0) {
                                HomeFragment.this.onPad16Touch(_lastPress[pointer], false);
                            }
                            _touchX[pointer] = x;
                            _touchY[pointer]  = y;
                            _lastPress[pointer] = padIndex;
                            CCStatus status = CCStatusesSceneManager.getInstance()._frontScene.get(_lastPress[pointer]);
                            _originalValue[pointer] = status._value.getSafeInt(0);;
                            HomeFragment.this.onPad16Touch(_lastPress[pointer], true);
                        }
                    } else if (action == MotionEvent.ACTION_CANCEL) {
                        if (_lastPress[pointer] >= 0) {
                            HomeFragment.this.onPad16Touch(_lastPress[pointer], false);
                    }
                    _lastPress[pointer] = -1;
	                } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {
	                    if (_lastPress[pointer] >= 0) {
	                        HomeFragment.this.onPad16Touch(_lastPress[pointer], false);
	                    }
	                    _lastPress[pointer] = -1;
	                } else if (mainParams._padDragMode.getValue() == MXWatchableDragMode.DRAG_VALUE && action == MotionEvent.ACTION_MOVE) {
	                    if (_lastPress[pointer] >= 0) {
	                        int disX = x - _touchX[pointer];
	                        int disY = _touchY[pointer] - y;
	                        CCStatus status = CCStatusesSceneManager.getInstance()._frontScene.get(_lastPress[pointer]);
	                        int original = _originalValue[pointer];
	                        int distance = disX + disY;
	                        int range = status._value.getMax() - status._value.getMin();
	                        int dispRange = binding.recyclerButtons.getWidth();

	                        // move dispRange = change range * moveD;
	                        double moveD = 0.03;
	                        double f = original;
	                        double add = distance * moveD * dispRange / range;
	                        int newValue = (int)(f + add);
	                        if (newValue < status._value.getMin()) {
	                            newValue = status._value.getMin();
	                        }
	                        if (newValue > status._value.getMax()) {
	                            newValue = status._value.getMax();
	                        }
	                        if (status._value.getValue() != newValue) {
	                            status._value.setValue(newValue);
	                            status.sendThis();
	                            updateFieldValueList(status, false);
	                        }
	                    }
	                } else if (action == MotionEvent.ACTION_MOVE) {
	                } else {
	                }
	            }
	        }catch(Throwable ex) {
	            Log.e(AppConstant.TAG, ex.getMessage(), ex);
	        }
	        return !proc; //スクロールをハンドルしなくする
	    }
広告を表示しています。

2025思い出せる範囲トップ