自定义 android 组件

Custom android component

我正在尝试制作自定义 android 组件。出于这个原因,我让我的 class 扩展了 "View",但是 class 已经扩展了 "BaseAdapter"。该组件应该是这样的:http://www.brightec.co.uk/blog/android-listview-alphabet-scroller 但它应该出现在 CustomView 组件下​​的 Palette 中。

这是应该继承 View 而不是 BaseElement 的 class:

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;
}
}

这是实例化它并将其用作适配器的 class。

public class 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 它,但似乎不可能用一个 class 扩展两个 class。是否有另一种方法可以使该项目像单个组件一样运行?

在Java中,一个Class只能直接扩展一个Class(但实现几个接口)。

由于您没有提交自己的代码,因此很难给您一些实质性的反馈,但这里有一些想法:

  • 您能否将自定义视图设为 XML,并将您的 class 包含在 "tools:context" 属性中?

  • 您不能只在 Activity 或 Fragment 中构建您想要的功能吗?你 class 必须扩展 BaseAdapter 吗?可以改用合成吗?

我不知道这是否对你有帮助,但祝你好运。

我认为您需要先通过扩展 View 创建 class,然后将您的 AlphabetListAdapter 作为成员变量包含在其中,并通过 getter 和 setter 公开它。

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();