Android 實(shí)現(xiàn)自定義圓形listview功能的實(shí)例代碼
最近遇到一個(gè)需求需要圓形listview作為懸浮窗,費(fèi)了九牛二虎之力終于開發(fā)出來(lái)了,特別有成就感,下面分享下案例,項(xiàng)目原因,只能分享一部分供大家參考
1.有圖有真相
下面就來(lái)講解下代碼:
1.自定義listview
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class CircleListView extends ViewGroup { private static final double intervalAngel = 60;//子view之間的間隔角 int circleR;//圓的半徑 int ccx;//圓心的x軸坐標(biāo) int ccy;//圓心的y軸坐標(biāo) double angel = 0;//偏移角度 private float oldTouchY;//上一次觸摸的y軸位置 private boolean isScrolling = false;//是否在滑動(dòng)狀態(tài) private Bitmap circleBitmap = null; private Rect src; private Rect dst; private Paint paint; private Adapter adapter = new Adapter(this) { @Override public View getView(int position) { return new View(getContext()); } }; public CircleListView(Context context) { super(context); setWillNotDraw(false); paint = new Paint(); } public CircleListView(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); paint = new Paint(); // TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleListView); // setCircleBitMap(ta.getResourceId(R.styleable.CircleListView_circleDrawable, 0)); // ta.recycle(); } private void setCircleBitMap(int drawableId) { if (drawableId != 0) { circleBitmap = BitmapFactory.decodeResource(getResources(), drawableId); } else { circleBitmap = null; } } public void setAdapter(Adapter adapter) { this.adapter = adapter; refreshList(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { measureChildren(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (circleBitmap != null) { if (src == null) { src = new Rect(); } src.left = 0; src.top = 0; src.right = circleBitmap.getWidth(); src.bottom = circleBitmap.getHeight(); if (dst == null) { dst = new Rect(); } dst.left = ccx - circleBitmap.getWidth()/4; dst.top = ccy - circleBitmap.getHeight()/4; dst.right = ccx + circleBitmap.getWidth()/4; dst.bottom = ccy + circleBitmap.getHeight()/4; canvas.drawBitmap(circleBitmap, src, dst, paint); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { circleR = (getRight() - getLeft()) / 10 * 5; ccy = (int) (getHeight() * 0.5); ccx = getWidth() / 2; for (int i = 0; i < adapter.getCount(); i++) { View childView = getChildAt(i); double childViewAngel = i * intervalAngel + angel; int x = ccx + (int) (Math.sin(Math.toRadians(childViewAngel)) * circleR*0.6); int y = ccy - (int) (Math.cos(Math.toRadians(childViewAngel)) * circleR*0.6); int vl = x - childView.getMeasuredWidth() / 2; int vt = y - childView.getMeasuredHeight() / 2; int vr = x + childView.getMeasuredWidth() / 2; int vb = y + childView.getMeasuredHeight() / 2; childView.layout(vl, vt, vr, vb ); } } // @Override // public boolean dispatchTouchEvent(MotionEvent ev) { // switch (ev.getAction()) { // case MotionEvent.ACTION_DOWN: // oldTouchY = ev.getY(); // super.dispatchTouchEvent(ev); // return true; // case MotionEvent.ACTION_MOVE: // if (!isScrolling && Math.abs(oldTouchY - ev.getY()) > 50) { // isScrolling = true; // float offSetY = 0; // oldTouchY = ev.getY(); // angel += offSetY / 20; // requestLayout(); // return true; // } else if (isScrolling) { // float offSetY = ev.getY() - oldTouchY; // oldTouchY = ev.getY(); // if ((angel + offSetY / 20) < ((adapter.getCount() - 1) * -intervalAngel)) { // angel = (adapter.getCount() - 1) * -intervalAngel; // } else if ((angel + offSetY / 20) > 0) { // angel = 0; // } else { // angel += offSetY / 20; // } // requestLayout(); // return true; // } // return super.dispatchTouchEvent(ev); // case MotionEvent.ACTION_UP: // boolean notDispatch = isScrolling; // isScrolling = false; // if (notDispatch) { // return false; // } else { // performClick(); // return super.dispatchTouchEvent(ev); // } // default: // isScrolling = false; // return super.dispatchTouchEvent(ev); // } // } protected void refreshList() { removeAllViews(); for (int i = 0; i < adapter.getCount(); i++) { if (i == 0 && angel < -intervalAngel * (adapter.getCount() - 1)) { angel = -intervalAngel * (adapter.getCount() - 1); } addView(adapter.getView(i)); if (adapter.getCount() == 1) { setPosition(0); } } invalidate(); } protected void setPosition(int position) { angel = -position * intervalAngel; } }
2.實(shí)體類
import android.graphics.drawable.Drawable; public class Files { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getApp_name() { return app_name; } public void setApp_name(String app_name) { this.app_name = app_name; } public String getPackagename() { return packagename; } public void setPackagename(String packagename) { this.packagename = packagename; } public int getImg_bg_id() { return img_bg_id; } public void setImg_bg_id(int img_bg_id) { this.img_bg_id = img_bg_id; } public boolean isShow() { return isShow; } public void setShow(boolean show) { isShow = show; } private Drawable imgDrawable; public Drawable getImgDrawable() { return imgDrawable; } public void setImgDrawable(Drawable imgDrawable) { this.imgDrawable = imgDrawable; } private boolean isShow; private String app_name; private String packagename; private int img_bg_id; }
3.適配器
import android.view.View; import java.util.ArrayList; public abstract class Adapter { private CircleListView circleListView; private ArrayList<Files> allAppList; public Adapter(CircleListView circleListView) { this.circleListView = circleListView; } public int getCount() { return allAppList.size(); } public abstract View getView(int position); public void notifyDataChanged() { circleListView.refreshList(); } public void setPosition(int position) { if (position > getCount() - 1) { position = getCount() - 1; } else if (position < 0) { position = 0; } circleListView.setPosition(position); } }
4.float.xml 引用:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/float_btn" android:layout_width="79px" android:layout_height="79px" android:scaleType="fitCenter" android:layout_centerInParent="true" android:background="@drawable/main_selector_floatbtn" android:clickable="true" /> <RelativeLayout android:id="@+id/float_area" android:layout_width="300px" android:layout_height="300px" android:layout_centerInParent="true" android:background="@drawable/float_display_bg" android:visibility="gone"> <com.xinrui.headsettest.circlelistview.CircleListView android:id="@+id/circle_list_view" android:layout_width="300px" android:layout_height="300px" android:layout_centerHorizontal="true"/> <ImageView android:id="@+id/float_main_img" android:layout_width="70px" android:layout_height="70px" android:scaleType="fitCenter" android:layout_centerInParent="true" android:background="@drawable/float_main_icon" android:clickable="true"/> </RelativeLayout> </RelativeLayout>
5.Activity中應(yīng)用:
import android.app.Activity; import android.os.Bundle; import android.provider.ContactsContract; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.xinrui.headsettest.circlelistview.Adapter; import com.xinrui.headsettest.circlelistview.CircleListView; import com.xinrui.headsettest.circlelistview.Files; import java.util.ArrayList; public class FloatActivity extends Activity implements View.OnClickListener{ private ImageView floatImg, float_main_img; private RelativeLayout float_area; private CircleListView circle_list_view; private Adapter adapter; private ArrayList<Files> appDataList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.float_layout); getData(); init(); } private void getData(){ appDataList=new ArrayList<>(); Files files = new Files(); files.setApp_name(this.getResources().getString(R.string.calculator_txt)); files.setImg_bg_id(R.drawable.main_selector_calculator); appDataList.add(files); Files files0 = new Files(); files0.setApp_name(this.getResources().getString(R.string.calendar_txt)); files0.setImg_bg_id(R.drawable.main_selector_calendar); appDataList.add(files0); Files files1 = new Files(); files1.setApp_name(this.getResources().getString(R.string.timer_txt)); files1.setImg_bg_id(R.drawable.main_selector_clock); appDataList.add(files1); Files files2 = new Files(); files2.setApp_name(this.getResources().getString(R.string.vip_txt)); files2.setImg_bg_id(R.drawable.main_selector_vip); appDataList.add(files2); Files files3 = new Files(); files3.setApp_name(this.getResources().getString(R.string.screen_shots_txt)); files3.setImg_bg_id(R.drawable.main_selector_screenshot); appDataList.add(files3); Files files4 = new Files(); files4.setApp_name(this.getResources().getString(R.string.recording_screen_txt)); files4.setImg_bg_id(R.drawable.main_selector_recordingscreen); appDataList.add(files4); } private void init() { float_area = (RelativeLayout) findViewById(R.id.float_area); floatImg = (ImageView) findViewById(R.id.float_btn); float_main_img = (ImageView) findViewById(R.id.float_main_img); float_main_img.bringToFront(); floatImg.setOnClickListener(this); float_main_img.setOnClickListener(this); circle_list_view = findViewById(R.id.circle_list_view); adapter = new Adapter(circle_list_view) { @Override public View getView(final int position) { View view = LayoutInflater.from(FloatActivity.this).inflate(R.layout.item_app,null); TextView app_name = view.findViewById(R.id.app_name); ImageView app_img = view.findViewById(R.id.app_img); ImageView delete_img = view.findViewById(R.id.delete_icon); delete_img.bringToFront(); final Files files = appDataList.get(position); app_name.setText(files.getApp_name()); app_img.setImageResource(files.getImg_bg_id()); if(files.isShow()){ delete_img.setVisibility(View.VISIBLE); }else{ delete_img.setVisibility(View.INVISIBLE); } delete_img.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { appDataList.remove(position); Files file = new Files(); file.setShow(false); file.setImg_bg_id(R.drawable.main_selector_additem); file.setApp_name(FloatActivity.this.getResources().getString(R.string.custom_txt)); appDataList.add(position,file); adapter.notifyDataChanged(); } }); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(FloatActivity.this,"my is "+files.getApp_name(),Toast.LENGTH_SHORT).show(); } }); view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { if(!files.getApp_name().equals(FloatActivity.this.getResources().getString(R.string.custom_txt))) { for (Files file : appDataList) { if (file.getApp_name().equals(files.getApp_name())) { file.setShow(true); } else { file.setShow(false); } } adapter.notifyDataChanged(); } return true; } }); return view; } @Override public int getCount() { return appDataList.size(); } }; circle_list_view.setAdapter(adapter); adapter.setPosition(0); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.float_main_img: float_area.setVisibility(View.GONE); floatImg.setVisibility(View.VISIBLE); break; case R.id.float_btn: float_area.setVisibility(View.VISIBLE); floatImg.setVisibility(View.GONE); break; } } }
大功告成就這樣實(shí)現(xiàn)了圓形listview…
到此這篇關(guān)于Android 實(shí)現(xiàn)自定義圓形listview功能的實(shí)例代碼的文章就介紹到這了,更多相關(guān)android 自定義圓形listview內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 進(jìn)度條自動(dòng)前進(jìn)效果的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 進(jìn)度條自動(dòng)前進(jìn)效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07Android利用Senser實(shí)現(xiàn)不同的傳感器
這篇文章主要為大家詳細(xì)介紹了Android利用Senser實(shí)現(xiàn)不同傳感器的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02Android自定義ViewGroup實(shí)現(xiàn)標(biāo)簽流容器FlowLayout
這篇文章主要介紹了Android自定義ViewGroup實(shí)現(xiàn)FlowLayout標(biāo)簽流容器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android實(shí)現(xiàn)第三方登錄的上拉展開,下拉隱藏,下拉隱藏示例
本篇文章抽出了項(xiàng)目登錄界面中實(shí)現(xiàn)的第三方登錄,用戶可以上拉展開,下拉隱藏第三方登錄這么一個(gè)效果,提高用戶和軟件的交互性。有興趣的可以了解一下。2017-01-01Java4Android開發(fā)教程(五)java的基本數(shù)據(jù)類型特征
這篇文章主要介紹了Java4Android開發(fā)教程的第五篇文章java的基本數(shù)據(jù)類型特征,需要的朋友可以參考下2014-10-10Android指紋識(shí)別認(rèn)識(shí)和基本使用詳解
這篇文章主要為大家詳細(xì)介紹了Android指紋識(shí)別認(rèn)識(shí)和基本的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Android 簡(jiǎn)單實(shí)現(xiàn)一個(gè)流式布局的示例
本篇文章主要介紹了Android 簡(jiǎn)單實(shí)現(xiàn)一個(gè)流式布局的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-02-02關(guān)于Android短信驗(yàn)證碼的獲取的示例
本篇文章主要介紹了關(guān)于Android短信驗(yàn)證碼的獲取的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-08-08詳解Android封裝一個(gè)全局的BaseActivity
這篇文章主要介紹了詳解Android封裝一個(gè)全局的BaseActivity,對(duì)封裝感興趣的同學(xué),可以參考下2021-04-04