Пользовательский компонент Android

Я пытаюсь создать собственный компонент Android. По этой причине я сделал так, чтобы мой класс расширял «View», но класс уже расширял «BaseAdapter». Компонент должен выглядеть примерно так: http://www.brightec.co.uk/blog/android-listview-alphabet-scroller, но он должен появиться в палитре под компонентом CustomView.

Это класс, который должен наследовать View вместо BaseElement:

public class AlphabetListAdapter extends BaseAdapter {

public static abstract class Row {}

public static final class Section extends Row {
    public final String text;

    public Section(String text) {
        this.text = text;
    }
}

public static final class Item extends Row {
    public final String text;

    public Item(String text) {
        this.text = text;
    }
}

private List<Row> rows;

public void setRows(List<Row> rows) {
    this.rows = rows;
}
}

И это класс, который создает экземпляр и использует его в качестве адаптера.

открытый класс MainActivity расширяет ListActivity {

private AlphabetListAdapter adapter = new AlphabetListAdapter();

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

    for (String country : countries) {
        rows.add(new Item(country));
    }

    adapter.setRows(rows);
    setListAdapter(adapter);     //not able to do this with a class that extends View

    updateList();
}

}

Весь исходный код доступен по адресу: https://github.com/brightec/AlphabetScroller (это не мой код, это пример, который я нашел в Интернете)

Есть ли способ сделать это? Я пытался найти его в Google, но похоже, что один класс не может расширить два класса. Есть ли другой способ заставить этот проект работать как один компонент?


person user2700896    schedule 15.03.2015    source источник


Ответы (2)


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

public class AlphabeticListView extends View {

    private ListView mListView;
    private LinearLayout mSideIndex;

    private AlphabetListAdapter adapter;
    private List<Object[]> alphabet;
    private HashMap<String, Integer> sections;

    private static float sideIndexX;
    private static float sideIndexY;
    private int sideIndexHeight;
    private int indexListSize;

    private GestureDetector mGestureDetector;

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

        init();
    }

    public AlphabeticListView(Context context, AttributeSet attrs) {
        super(context, attrs);

        init();
    }

    public AlphabeticListView(Context context) {
        super(context);

        init();
    }

    private void init() {
        Context context = getContext();

        mGestureDetector = new GestureDetector(getContext(), 
                new SideIndexGestureListener());

        mListView = new ListView(context); // TODO add layoutParams and other attributes you might need.

        mSideIndex = new LinearLayout(context); // TODO add layoutParams and other attributes you might need.
    }

    public AlphabetListAdapter getAdapter() {
        return adapter;
    }

    public void setAdapter(AlphabetListAdapter adapter) {
        mListView.setAdapter(adapter);
        this.adapter = adapter;
    }

    public List<Object[]> getAlphabet() {
        return alphabet;
    }

    public void setAlphabet(List<Object[]> alphabet) {
        this.alphabet = alphabet;
    }

    public HashMap<String, Integer> getSections() {
        return sections;
    }

    public void setSections(HashMap<String, Integer> sections) {
        this.sections = sections;
    }

    public void updateList() {
        mSideIndex.removeAllViews();
        indexListSize = alphabet.size();
        if (indexListSize < 1) {
            return;
        }

        int indexMaxSize = (int) Math.floor(mSideIndex.getHeight() / 20);
        int tmpIndexListSize = indexListSize;
        while (tmpIndexListSize > indexMaxSize) {
            tmpIndexListSize = tmpIndexListSize / 2;
        }
        double delta;
        if (tmpIndexListSize > 0) {
            delta = indexListSize / tmpIndexListSize;
        } else {
            delta = 1;
        }

        TextView tmpTV;
        for (double i = 1; i <= indexListSize; i = i + delta) {
            Object[] tmpIndexItem = alphabet.get((int) i - 1);
            String tmpLetter = tmpIndexItem[0].toString();

            tmpTV = new TextView(getContext());
            tmpTV.setText(tmpLetter);
            tmpTV.setGravity(Gravity.CENTER);
            tmpTV.setTextSize(15);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT, 1);
            tmpTV.setLayoutParams(params);
            mSideIndex.addView(tmpTV);
        }

        sideIndexHeight = mSideIndex.getHeight();

        mSideIndex.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // now you know coordinates of touch
                sideIndexX = event.getX();
                sideIndexY = event.getY();

                // and can display a proper item it country list
                displayListItem();

                return false;
            }
        });
    }

    public void displayListItem() {
        sideIndexHeight = mSideIndex.getHeight();
        // compute number of pixels for every side index item
        double pixelPerIndexItem = (double) sideIndexHeight / indexListSize;

        // compute the item index for given event position belongs to
        int itemPosition = (int) (sideIndexY / pixelPerIndexItem);

        // get the item (we can do it since we know item index)
        if (itemPosition < alphabet.size()) {
            Object[] indexItem = alphabet.get(itemPosition);
            int subitemPosition = sections.get(indexItem[0]);

            // ListView listView = (ListView) findViewById(android.R.id.list);
            mListView.setSelection(subitemPosition);
        }
    }

    class SideIndexGestureListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, 
                float distanceY) {
            sideIndexX = sideIndexX - distanceX;
            sideIndexY = sideIndexY - distanceY;

            if (sideIndexX >= 0 && sideIndexY >= 0) {
                displayListItem();
            }

            return super.onScroll(e1, e2, distanceX, distanceY);
        }
    }
}

И в свою MainActivity добавьте следующее:

AlphabeticListView listView = 
        (AlphabeticListView) findViewById(R.id.alphabeticListView1);

listView.setAdapter(adapter);
listView.setAlphabet(alphabet);
listView.setSections(sections);
listView.updateList();
person Naveen Dissanayake    schedule 16.03.2015
comment
использование этого кода привело к пустому экрану (ничего не отображается). Не могли бы вы добавить дополнительную информацию? Я новичок в java и не очень хорошо в этом разбираюсь. У вас есть весь код в репозитории github. - person user2700896; 16.03.2015
comment
Извини, приятель, у меня нет времени заниматься всем этим. Но я отредактирую ответ, чтобы вы могли начать работу. - person Naveen Dissanayake; 16.03.2015

В Java класс может напрямую расширять только один класс (но реализовывать несколько интерфейсов).

Поскольку вы не отправляете свой собственный код, трудно дать вам какой-то существенный отзыв, но вот некоторые мысли:

  • Можете ли вы создать свой собственный вид в виде XML и включить свой класс с атрибутом «tools:context»?

  • Разве вы не можете просто создать нужную функциональность в Activity или Fragment? И должен ли ваш класс расширять BaseAdapter? Можете ли вы использовать композицию вместо этого?

Я не знаю, поможет ли это вам вообще, но желаю удачи.

person LeFex    schedule 15.03.2015
comment
спасибо за ответ, не могли бы вы объяснить пример кода, который я отправил (тот, что на github) - person user2700896; 16.03.2015
comment
Что ж, глядя на код, я бы сказал, что класс, от которого вы хотите получить поведение, — это просто адаптер, который является вспомогательным классом для создания макетов. Что вам нужно сделать, так это использовать этот класс так же, как и в MainActivity; не расширяя его, а просто создавая экземпляр и используя его методы. - person LeFex; 16.03.2015