Android: включить полосы прокрутки в представлении на основе холста - PullRequest
1 голос
/ 02 февраля 2011

У меня есть пользовательский вид, который расширяет вид.Он отображает нарисованные фигуры и позволяет пользователю добавлять эти рисунки посредством рисования сенсорных событий в представлении через onDraw.

Я включил ScaleGestureDetector, чтобы пользователь мог увеличивать конкретный участок и рисовать,но так как я использую рисование одним касанием, они не могут использовать свой палец для перемещения по увеличенному представлению.

Я попытался включить полосы прокрутки для представления таким образом, чтобы при увеличении масштаба полосы прокруткиотображаются и могут быть использованы пользователем для панорамирования ... но я просто не могу отобразить полосы прокрутки.

По сути, я делаю, чтобы вызвать метод View * awakenScrollBars() в моемМетод ScaleListener onScale() при увеличении масштаба пользователя, который запускает invalidate().Я включил полосы прокрутки как через XML, так и программно в onCreate(), но я не могу вызвать отображение полос прокрутки.Вот мой XML:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.package.name.Canvas
    android:id="@+id/canvas"
    android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:focusable="true"
        android:scrollbars="horizontal|vertical" />
</FrameLayout>

А вот мой onCreate ():

// set scrollbars
setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);

В onDraw я могу убедиться, что полосы прокрутки включены с помощью isHorizontalScrollBarEnabled() и isVerticalScrollBarEnabled()и awakenScrollBars() в onScale() возвращает значение true, но полосы прокрутки просто не видны.

Есть предложения о том, как поступить?Содержать пользовательский вид в макете ScrollView не представляется возможным, поскольку он поддерживает только вертикальную прокрутку.

Спасибо,

Пол

Ответы [ 4 ]

11 голосов
/ 01 июня 2011

Если вы создаете свой пользовательский вид программно, то ответ следующий: чтобы показать полосы прокрутки в классе пользовательского представления, во время инициализации должен быть вызван метод initializeScrollbars (например, в конструкторе).

Этот метод принимает один очень непонятный параметр типа TypedArray.Чтобы получить подходящий экземпляр TypedArray, вам нужно создать настраиваемую стилевую запись - просто создайте файл «attrs.xml» в каталоге «res \ values» со следующим содержимым:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="View">
    <attr name="android:background"/>
    <attr name="android:clickable"/>
    <attr name="android:contentDescription"/>
    <attr name="android:drawingCacheQuality"/>
    <attr name="android:duplicateParentState"/>
    <attr name="android:fadeScrollbars"/>
    <attr name="android:fadingEdge"/>
    <attr name="android:fadingEdgeLength"/>
    <attr name="android:fitsSystemWindows"/>
    <attr name="android:focusable"/>
    <attr name="android:focusableInTouchMode"/>
    <attr name="android:hapticFeedbackEnabled"/>
    <attr name="android:id"/>
    <attr name="android:isScrollContainer"/>
    <attr name="android:keepScreenOn"/>
    <attr name="android:longClickable"/>
    <attr name="android:minHeight"/>
    <attr name="android:minWidth"/>
    <attr name="android:nextFocusDown"/>
    <attr name="android:nextFocusLeft"/>
    <attr name="android:nextFocusRight"/>
    <attr name="android:nextFocusUp"/>
    <attr name="android:onClick"/>
    <attr name="android:padding"/>
    <attr name="android:paddingBottom"/>
    <attr name="android:paddingLeft"/>
    <attr name="android:paddingRight"/>
    <attr name="android:paddingTop"/>
    <attr name="android:saveEnabled"/>
    <attr name="android:scrollX"/>
    <attr name="android:scrollY"/>
    <attr name="android:scrollbarAlwaysDrawHorizontalTrack"/>
    <attr name="android:scrollbarAlwaysDrawVerticalTrack"/>
    <attr name="android:scrollbarDefaultDelayBeforeFade"/>
    <attr name="android:scrollbarFadeDuration"/>
    <attr name="android:scrollbarSize"/>
    <attr name="android:scrollbarStyle"/>
    <attr name="android:scrollbarThumbHorizontal"/>
    <attr name="android:scrollbarThumbVertical"/>
    <attr name="android:scrollbarTrackHorizontal"/>
    <attr name="android:scrollbarTrackVertical"/>
    <attr name="android:scrollbars"/>
    <attr name="android:soundEffectsEnabled"/>
    <attr name="android:tag"/>
    <attr name="android:visibility"/>
</declare-styleable>
</resources>

Также полный код инициализации полос прокрутки(поместите его в свой конструктор пользовательских представлений):

setHorizontalScrollBarEnabled(true);
setVerticalScrollBarEnabled(true);

TypedArray a = context.obtainStyledAttributes(R.styleable.View);
initializeScrollbars(a);
a.recycle();

PS решение было протестировано на Android 2.0

Я забыл добавить: также должны быть методы "computeVerticalScrollRange" и "computeHor horizontalScrollRange"переопределены.Они должны просто вернуть воображаемую ширину и высоту холста.

3 голосов
/ 03 июня 2013

Как все мы знаем, представление Android имеет возможность прокрутки.

Для отображения полос прокрутки необходимо сделать две вещи.

  1. add android: scrollbars = "горизонтальный| vertical "в объявлении xml вашего представления
  2. переопределяет метод computeHor horizontalScrollRange / computeVerticalScrollRange класса View, делая возвращаемые значения большими, чем возвращаемые значения метода computeHor horizontalScrollExtent / computeVerticalScrollExtent

После этого полосы прокрутки должны автоматически отображаться при вызове метода scrollTo или scrollBy.

Извините за плохой английский, если есть какие-либо заклинания или грамматические ошибки.Вы можете попробовать это:
activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
tools:context=".MainActivity" >

<com.netease.test.testscroll.ScrollImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFCCCCCC"
    android:scrollbars="horizontal|vertical"
    android:src="@drawable/pp" />

</LinearLayout>

ScrollImageView - это пользовательское представление, вы можете реализовать так:

public class ScrollImageView extends ImageView {
    static final String TAG = "ScrollImageView";
    private Rect mContentRect = new Rect();
    GestureDetector mDetector;
    OnGestureListener mListener = new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            Log.i("onScroll", "before:distanceX = " + distanceX
                    + ", distanceY = " + distanceY);
            scrollBy((int)distanceX, (int)distanceY);
            // boolean value = awakenScrollBars();
            Log.i("onScroll", "after:current ScrollX=" + getScrollX()
                    + ", ScrollY=" + getScrollY());
            return true;
        }
    };
    public ScrollImageView(Context context) {
        this(context, null);
    }
    public ScrollImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public ScrollImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setScaleType(ScaleType.MATRIX);
        mDetector = new GestureDetector(getContext(), mListener);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mDetector.onTouchEvent(event);
        return true;
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mContentRect.set(getPaddingLeft(), getPaddingTop(), getWidth()
                - getPaddingRight(), getHeight() - getPaddingBottom());
    }
    @Override
    protected int computeHorizontalScrollRange() {
        return getDrawable().getIntrinsicWidth();
    }
    @Override
    protected int computeHorizontalScrollExtent() {
        return mContentRect.width();
    }
    @Override
    protected int computeHorizontalScrollOffset() {
        return Math.max(0, getScrollX());
    }
    private int getScrollRangeX() {
        return computeHorizontalScrollRange() - computeHorizontalScrollExtent();
    }
    @Override
    protected int computeVerticalScrollRange() {
        return getDrawable().getIntrinsicHeight();
    }
    @Override
    protected int computeVerticalScrollExtent() {
        return mContentRect.height();
    }
    @Override
    protected int computeVerticalScrollOffset() {
        return Math.max(0, getScrollY());
    }
    private int getScrollRangeY() {
        return computeVerticalScrollRange() - computeVerticalScrollExtent();
    }
}

указать большой png с именем "pp"и просто прокрутите изображение, вы должны увидеть полосы прокрутки.

3 голосов
/ 21 декабря 2011

Для тех из вас, кто пытается добавить полосы прокрутки к пользовательскому ViewGroup (а не View) или к одному из его подклассов, обязательно добавьте setWillNotDraw(false); в конструктор в дополнение к тому, что Руслан Янчишин сказал вответ выше.

Больше информации можно найти в этом вопросе и моем ответе .

0 голосов
/ 27 ноября 2014

Метод "initializeScrollbars" был удален с уровня API 21 и выше.

    final TypedArray a = context.obtainStyledAttributes(R.styleable.View);
    initializeScrollbars(a);//removed method in Lollipop.
    a.recycle();

См. https://developer.android.com/sdk/api_diff/21/changes/android.view.View.html. initializeScrollbars не определен?

FYI. Мы больше не можем использовать метод initializeScrollbars (a) в Lollipop.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...