自定义 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();
我正在尝试制作自定义 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();