user2700896
user2700896

Reputation: 579

Custom android component

I am trying to make a custom android component. For that reason I have make my class extend "View", but the class is already extending "BaseAdapter". The component should be something like this: http://www.brightec.co.uk/blog/android-listview-alphabet-scroller but it should appear in the Palette under the CustomView component.

This is the class that should inherit View instead of 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;
}
}

And this is the class that instantiates it, and uses it as an adapter.

public class MainActivity extends 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();
}

}

The whole source is available on: https://github.com/brightec/AlphabetScroller (ths is not my code, it is an example I found online)

Is there a way to do that? I have tried to Google it, but it seems like it is not possible for a single class to extend two classes. Is there another way of making this project to act like a single component?

Upvotes: 3

Views: 144

Answers (2)

Naveen Dissanayake
Naveen Dissanayake

Reputation: 672

I think you need to create the class by extending View first then include your AlphabetListAdapter in as a member variable and expose that through getters and setters.

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

And in your MainActivity add the following:

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

listView.setAdapter(adapter);
listView.setAlphabet(alphabet);
listView.setSections(sections);
listView.updateList();

Upvotes: 1

LeFex
LeFex

Reputation: 258

In Java, a Class can only extend one Class directly (but implement several interfaces).

Since you're not submitting your own code, it's hard to give you some substantial feedback, but here are some thoughts:

  • Can you make your custom View as an XML, and include your class with the "tools:context" attribute?

  • Can't you just build the functionality you want in an Activity or a Fragment? And does you class have to extend BaseAdapter? Can you use composition instead?

I don't know if this helps you at all, but best of luck.

Upvotes: 0

Related Questions