Android scroll and drag child in custom Viewgroup inside scrollview

60 views Asked by At

i want to drag and position a child in my Viewgroup. While dragging and scrolling my child shoud stay at top or bottom but i cant figure out how to do that.

Xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"

    tools:context=".ui.slideshow.SlideshowFragment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
   >

    <CalendarView
        android:id="@+id/calender_slideshow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/blue_grey"

        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


        <de.littles.recipes.DaylyNotesLayout
            android:id="@+id/daylynotes"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/calender_slideshow"
            app:layout_constraintStart_toStartOf="parent">


        </de.littles.recipes.DaylyNotesLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

My custom viewgroup

public class DaylyNotesLayout extends ViewGroup implements View.OnTouchListener, View.OnLongClickListener{
    private List<DayScheduleData> dayScheduleData = new ArrayList<>();
    int deviceWidth, deviceHeight;
    float dX;
    float dY;
    int lastAction;
    Point deviceDisplay = new Point();
    private final int columnHeight = 115;

    public DaylyNotesLayout(Context context) {
        super(context);
        init(context);
      
    }

    public DaylyNotesLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);

    }

    public DaylyNotesLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);

    }

    public DaylyNotesLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);

    }

    private void init(Context context) {
        final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

        display.getSize(deviceDisplay);
        deviceWidth = deviceDisplay.x;
        deviceHeight = deviceDisplay.y;
    }

    public void clear() {

        dayScheduleData.clear();
        super.removeAllViews();

    }

    public void addNewView(View child, int startTime, int length) {
        DayScheduleData childViewData = new DayScheduleData(child.getTag().toString(), startTime, length);
        dayScheduleData.add(childViewData);
        child.setOnTouchListener(this);

        super.addView(child);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int count = getChildCount();
        int curHeight, curLeft, curTop, maxHeight;
        int childLeft = this.getPaddingLeft() + 80;
        int childTop = this.getPaddingTop();
        int childRight = this.getMeasuredWidth() - 20;
        int childBottom;
        int childWidth = childRight;
        int childHeight;
        maxHeight = 0;
        int height = 0;
        for (int x = 0; x < count; x++) {
            View child = getChildAt(x);
            int start = dayScheduleData.get(x).getStartTime();
            curTop = start * columnHeight - (height * columnHeight);
            height = dayScheduleData.get(x).getLength();
            childBottom = childTop + (columnHeight * height) + this.getPaddingBottom();
            childHeight = childBottom - childTop;
            if (child.getVisibility() == GONE) {
                return;
            }
            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight - 5, MeasureSpec.EXACTLY));

            curHeight = childHeight;

            curLeft = childLeft;
            curTop += maxHeight;
            maxHeight = 0;

            child.layout(curLeft, curTop + 10, childRight, curTop + curHeight - 10);
            if (maxHeight < curHeight) {
                maxHeight = curHeight;
            }

        }

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int count = getChildCount();
        int maxHeight = columnHeight * 24;
        int maxWidth = 0;
        int childState = 0;
        int mLeftWidth = 0;
        int rowCount = 0;
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == GONE) {
                continue;
            }
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            maxWidth += Math.max(maxWidth, child.getMeasuredWidth());
            mLeftWidth += child.getMeasuredWidth();
            if ((mLeftWidth / deviceWidth) > rowCount) {

                rowCount++;
            } else {
                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
            }
            childState = combineMeasuredStates(childState, child.getMeasuredState());

        }
        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                resolveSizeAndState(maxHeight, heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT));


    }

    @Override
    protected void onDraw(Canvas canvas) {
        final float height = columnHeight;
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        TextPaint textPaint = new TextPaint();
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(24);
        textPaint.setAntiAlias(true);
        for (int x = 0; x < 24; x++) {
            paint.setStrokeWidth(2f);
            paint.setAlpha(255);
            if (x < 10) {
                canvas.drawText("0" + x + ":00", 10, x * height + textPaint.getTextSize(), textPaint);
            } else {
                canvas.drawText(x + ":00", 10, x * height + textPaint.getTextSize(), textPaint);
            }
            canvas.drawLine(0, x * height, getMeasuredWidth(), x * height, paint);

            paint.setStrokeWidth(2f);
            paint.setAlpha(50);
            canvas.drawLine(0, x * height + (height / 2), getMeasuredWidth(), x * height + (height / 2), paint);

        }
    }


    @Override
    public boolean onTouch(View view, MotionEvent event) {

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                dX = view.getX() - event.getRawX();
                dY = view.getY() - event.getRawY();
                lastAction = MotionEvent.ACTION_DOWN;
                break;

            case MotionEvent.ACTION_MOVE:
                ScrollView mainScrollView = getRootView().findViewById(R.id.scrollView);
                int dragTop = (int) (event.getRawY() - view.getHeight()/2);
                int dragBottom= (int) (event.getRawY() + view.getHeight()/2);
                int scrollY =mainScrollView.getScrollY();
                int scrollViewHeight = mainScrollView.getMeasuredHeight();
                Log.d("RawPos ",  "" + event.getRawY());
                Log.d("ScrollY", scrollY + "");

                mainScrollView.requestDisallowInterceptTouchEvent(true);

                if (dragBottom >  (scrollViewHeight -100)) {

                    mainScrollView.smoothScrollBy(0, 30);
                }
                if (dragTop< (200)) {

                    mainScrollView.smoothScrollBy(0, -30);

                }

                    view.setY(event.getRawY() + dY);


                lastAction = MotionEvent.ACTION_MOVE;
                break;

            case MotionEvent.ACTION_UP:

                view.setY((Math.round(view.getY() / columnHeight) * columnHeight) + 10);

                if (lastAction == MotionEvent.ACTION_DOWN)

                    break;

            default:
                return false;
        }
        return true;
    }

    @Override
    public boolean onLongClick(View v) {

        return true;
    }
    
}

Tried to set the child pos to top/bottom of viewgroup, adding smootscroll's value as offset and looked at scrollY and measuredheight, but i cant figure out how to get the correct values.

0

There are 0 answers