mData;
25 | private OnHomeClickedListener mListener;
26 |
27 | public HomeAdapter(Context context) {
28 | this.mContext = context;
29 | mData = new SparseArray<>();
30 | int[] colors = mContext.getResources().getIntArray(R.array.home_colors);
31 | String[] titles = mContext.getResources().getStringArray(R.array.home_titles);
32 | String[] subtitles = mContext.getResources().getStringArray(R.array.home_subtitles);
33 |
34 | for (int i = 0; i < colors.length; i++) {
35 | mData.append(i, new Showcase(colors[i], titles[i], subtitles[i]));
36 | }
37 |
38 | mData.append(colors.length, new Showcase(Color.parseColor("#37474F"), "", ""));
39 | }
40 |
41 | @Override
42 | public HomeAdapter.BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
43 | View view = LayoutInflater.from(mContext).inflate(viewType, parent, false);
44 |
45 | switch (viewType) {
46 | default:
47 | case VIEW_TYPE_SHOWCASE:
48 | return new ShowcaseViewHolder(view);
49 | case VIEW_TYPE_DEV:
50 | return new DevViewHolder(view);
51 | }
52 | }
53 |
54 | @Override
55 | public void onBindViewHolder(@NonNull HomeAdapter.BaseViewHolder viewHolder, int position) {
56 | Showcase data = mData.get(position);
57 | viewHolder.bind(data);
58 | }
59 |
60 | @Override
61 | public int getItemCount() {
62 | return mData == null ? 0 : mData.size();
63 | }
64 |
65 | @Override
66 | public int getItemViewType(int position) {
67 | if (position == mData.size() - 1) return VIEW_TYPE_DEV;
68 | return VIEW_TYPE_SHOWCASE;
69 | }
70 |
71 | //############################################################################################## VIEW HOLDERS
72 | class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
73 | View card;
74 |
75 | BaseViewHolder(View itemView) {
76 | super(itemView);
77 | card = itemView.findViewById(R.id.card_bg);
78 | }
79 |
80 | void bind(Showcase data){
81 | card.setBackgroundTintList(ColorStateList.valueOf(data.getColor()));
82 | card.setOnClickListener(this);
83 | }
84 |
85 | @Override
86 | public void onClick(View v) {
87 | if (mListener != null) {
88 | mListener.onItemClicked(getAdapterPosition());
89 | }
90 | }
91 | }
92 |
93 | class ShowcaseViewHolder extends BaseViewHolder {
94 | TextView title;
95 | TextView subtitle;
96 |
97 | ShowcaseViewHolder(View itemView) {
98 | super(itemView);
99 | title = itemView.findViewById(R.id.title);
100 | subtitle = itemView.findViewById(R.id.subtitle);
101 | }
102 |
103 | void bind(Showcase data) {
104 | super.bind(data);
105 | title.setText(data.getTitle());
106 | subtitle.setText(data.getSubtitle());
107 | }
108 | }
109 |
110 | class DevViewHolder extends BaseViewHolder {
111 |
112 | DevViewHolder(View itemView) {
113 | super(itemView);
114 | }
115 |
116 | void bind(Showcase data) {
117 | super.bind(data);
118 | }
119 | }
120 |
121 | //############################################################################################## CLICK LISTENER
122 | public void setOnHomeClickedListener(OnHomeClickedListener mListener) {
123 | this.mListener = mListener;
124 | }
125 |
126 | public interface OnHomeClickedListener {
127 | void onItemClicked(int position);
128 | }
129 | }
130 |
131 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ramijemli/sample/fragment/BackgroundBarSubFragment.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.sample.fragment;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.ColorStateList;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.Button;
12 | import android.widget.CheckBox;
13 | import android.widget.TextView;
14 |
15 | import com.flask.colorpicker.ColorPickerView;
16 | import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
17 | import com.ramijemli.sample.R;
18 | import com.ramijemli.sample.util.ScreenUtil;
19 |
20 | import androidx.annotation.NonNull;
21 | import androidx.annotation.Nullable;
22 | import androidx.fragment.app.Fragment;
23 | import butterknife.BindView;
24 | import butterknife.ButterKnife;
25 | import butterknife.OnClick;
26 | import butterknife.Unbinder;
27 |
28 |
29 | public class BackgroundBarSubFragment extends Fragment {
30 |
31 |
32 | //DRAW BACKGROUND BAR STATE
33 | @BindView(R.id.draw_bg_bar)
34 | CheckBox mDrawBgBar;
35 |
36 | //BACKGROUND BAR COLOR
37 | @BindView(R.id.bg_bar_color)
38 | Button mBgBarColor;
39 |
40 | //BACKGROUND BAR THICKNESS
41 | @BindView(R.id.bg_bar_thickness_value)
42 | TextView mBgBarThicknessValue;
43 |
44 |
45 | private OnBackgroundBarChangedListener mListener;
46 | private Unbinder unbinder;
47 |
48 | public BackgroundBarSubFragment() {
49 | }
50 |
51 | public static BackgroundBarSubFragment newInstance() {
52 | return new BackgroundBarSubFragment();
53 | }
54 |
55 | @Override
56 | public void onAttach(Context context) {
57 | super.onAttach(context);
58 | if (context instanceof OnBackgroundBarChangedListener) {
59 | mListener = (OnBackgroundBarChangedListener) context;
60 | } else {
61 | throw new RuntimeException(context.toString()
62 | + " must implement OnBackgroundBarChangedListener");
63 | }
64 | }
65 |
66 | @Override
67 | public void onDetach() {
68 | super.onDetach();
69 | mListener = null;
70 | }
71 |
72 | @Override
73 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
74 | View view = inflater.inflate(R.layout.sub_fragment_background_bar, container, false);
75 | unbinder = ButterKnife.bind(this, view);
76 | return view;
77 | }
78 |
79 | @Override
80 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
81 | super.onViewCreated(view, savedInstanceState);
82 | setupDrawBgBarState();
83 | }
84 |
85 | @Override
86 | public void onDestroyView() {
87 | mDrawBgBar.setOnCheckedChangeListener(null);
88 | unbinder.unbind();
89 | unbinder = null;
90 | super.onDestroyView();
91 | }
92 |
93 | //############################################################################################## BEHAVIOR
94 | private void setupDrawBgBarState() {
95 | mDrawBgBar.setOnCheckedChangeListener((buttonView, isChecked) -> {
96 | String text = String.valueOf(isChecked);
97 | mDrawBgBar.setText(Character.toUpperCase(text.charAt(0)) + text.substring(1).toLowerCase());
98 | if (mListener != null) {
99 | mListener.onDrawBgBarChanged(isChecked);
100 | }
101 | });
102 | }
103 |
104 | private void tweakBgThickness(int amount) {
105 | int value = getTextViewValue(mBgBarThicknessValue);
106 |
107 | int maxValue = (int) ScreenUtil.convertPixelsToDIP(getActivity(), getView().getMeasuredWidth() / 2);
108 | if (value + amount > maxValue) {
109 | value = maxValue;
110 | } else if (value + amount <= 0) {
111 | value = 0;
112 | } else {
113 | value += amount;
114 | }
115 |
116 | mBgBarThicknessValue.setText(value + " dp");
117 | if (mListener != null) {
118 | mListener.onBgBarThicknessChanged(ScreenUtil.convertDIPToPixels(getActivity(), value));
119 | }
120 | }
121 |
122 | private int getTextViewValue(TextView view) {
123 | String value = view.getText().toString();
124 | return Integer.parseInt(value.substring(0, value.length() - 3));
125 | }
126 |
127 | //############################################################################################## ACTIONS
128 | @OnClick(R.id.bg_bar_color)
129 | void bgBarColorAction() {
130 | ColorPickerDialogBuilder
131 | .with(getActivity())
132 | .setTitle("Choose Background bar color")
133 | .initialColor(Color.WHITE)
134 | .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
135 | .density(6)
136 | .setPositiveButton("SET", (dialog, selectedColor, allColors) -> {
137 | mBgBarColor.setBackgroundTintList(ColorStateList.valueOf(selectedColor));
138 | if (mListener != null) {
139 | mListener.onBgBarColorChanged(selectedColor);
140 | }
141 | })
142 | .setNegativeButton("DISMISS", (dialog, which) -> {
143 | })
144 | .build()
145 | .show();
146 | }
147 |
148 | @OnClick(R.id.increment_bg_bar_thickness)
149 | void incrementBgThicknessAction() {
150 | tweakBgThickness(1);
151 | }
152 |
153 | @OnClick(R.id.decrement_bg_bar_thickness)
154 | void decrementBgThicknessAction() {
155 | tweakBgThickness(-1);
156 | }
157 |
158 | //############################################################################################## LISTENER
159 | public interface OnBackgroundBarChangedListener {
160 | void onDrawBgBarChanged(boolean draw);
161 |
162 | void onBgBarColorChanged(int color);
163 |
164 | void onBgBarThicknessChanged(int thickness);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ramijemli/sample/fragment/BackgroundSubFragment.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.sample.fragment;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.ColorStateList;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.Button;
12 | import android.widget.CheckBox;
13 | import android.widget.TextView;
14 |
15 | import com.flask.colorpicker.ColorPickerView;
16 | import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
17 | import com.ramijemli.sample.R;
18 | import com.ramijemli.sample.util.ScreenUtil;
19 |
20 | import androidx.annotation.NonNull;
21 | import androidx.annotation.Nullable;
22 | import androidx.constraintlayout.widget.Group;
23 | import androidx.fragment.app.Fragment;
24 | import butterknife.BindView;
25 | import butterknife.ButterKnife;
26 | import butterknife.OnClick;
27 | import butterknife.Unbinder;
28 |
29 |
30 | public class BackgroundSubFragment extends Fragment {
31 |
32 | public static final String OFFSET_STATE_ARG = "BackgroundSubFragment.OFFSET_STATE_ARG";
33 |
34 | //DRAW BACKGROUND STATE
35 | @BindView(R.id.draw_background)
36 | CheckBox mDrawBackground;
37 |
38 | //BACKGROUND COLOR
39 | @BindView(R.id.background_color)
40 | Button mBackgroundColor;
41 |
42 | //BACKGROUND OFFSET
43 | @BindView(R.id.offset_value)
44 | TextView mOffsetValue;
45 | @BindView(R.id.offset_visibility)
46 | Group mOffsetGroup;
47 |
48 | private OnBackgroundChangedListener mListener;
49 | private Unbinder unbinder;
50 | private boolean enableOffset;
51 |
52 | public BackgroundSubFragment() {
53 | }
54 |
55 | public static BackgroundSubFragment newInstance() {
56 | return new BackgroundSubFragment();
57 | }
58 |
59 | @Override
60 | public void onAttach(Context context) {
61 | super.onAttach(context);
62 | if (context instanceof OnBackgroundChangedListener) {
63 | mListener = (OnBackgroundChangedListener) context;
64 | } else {
65 | throw new RuntimeException(context.toString()
66 | + " must implement OnBackgroundChangedListener");
67 | }
68 | }
69 |
70 | @Override
71 | public void onDetach() {
72 | super.onDetach();
73 | mListener = null;
74 | }
75 |
76 | @Override
77 | public void onCreate(Bundle savedInstanceState) {
78 | super.onCreate(savedInstanceState);
79 | if (getArguments() != null) {
80 | enableOffset = getArguments().getBoolean(OFFSET_STATE_ARG, false);
81 | }
82 | }
83 |
84 | @Override
85 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
86 | View view = inflater.inflate(R.layout.sub_fragment_background, container, false);
87 | unbinder = ButterKnife.bind(this, view);
88 | return view;
89 | }
90 |
91 | @Override
92 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
93 | super.onViewCreated(view, savedInstanceState);
94 | setupDrawBackgroundState();
95 | if(enableOffset){
96 | mOffsetGroup.setVisibility(View.VISIBLE);
97 | } else {
98 | mOffsetGroup.setVisibility(View.GONE);
99 | }
100 | }
101 |
102 | @Override
103 | public void onDestroyView() {
104 | mDrawBackground.setOnCheckedChangeListener(null);
105 | unbinder.unbind();
106 | unbinder = null;
107 | super.onDestroyView();
108 | }
109 |
110 | //############################################################################################## BEHAVIOR
111 | private void setupDrawBackgroundState() {
112 | mDrawBackground.setOnCheckedChangeListener((buttonView, isChecked) -> {
113 | String text = String.valueOf(isChecked);
114 | mDrawBackground.setText(Character.toUpperCase(text.charAt(0)) + text.substring(1).toLowerCase());
115 | if (mListener != null) {
116 | mListener.onDrawBackgroundChanged(isChecked);
117 | }
118 | });
119 | }
120 |
121 | private void tweakOffset(int amount) {
122 | int value = getTextViewValue(mOffsetValue);
123 |
124 | int maxValue = (int) ScreenUtil.convertPixelsToDIP(getActivity(), getView().getMeasuredWidth() / 2);
125 | if (value + amount > maxValue) {
126 | value = maxValue;
127 | } else if (value + amount <= 0) {
128 | value = 0;
129 | } else {
130 | value += amount;
131 | }
132 |
133 | mOffsetValue.setText(value + " dp");
134 |
135 | if (mListener != null) {
136 | mListener.onBackgroundOffsetChanged(ScreenUtil.convertDIPToPixels(getActivity(), value));
137 | }
138 | }
139 |
140 | private int getTextViewValue(TextView view) {
141 | String value = view.getText().toString();
142 | return Integer.parseInt(value.substring(0, value.length() - 3));
143 | }
144 |
145 | //############################################################################################## ACTIONS
146 | @OnClick(R.id.background_color)
147 | void backgroundAction() {
148 | ColorPickerDialogBuilder
149 | .with(getActivity())
150 | .setTitle("Choose background color")
151 | .initialColor(Color.WHITE)
152 | .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
153 | .density(6)
154 | .setPositiveButton("SET", (dialog, selectedColor, allColors) -> {
155 | mBackgroundColor.setBackgroundTintList(ColorStateList.valueOf(selectedColor));
156 | if (mListener != null) {
157 | mListener.onBackgroundColorChanged(selectedColor);
158 | }
159 | })
160 | .setNegativeButton("DISMISS", (dialog, which) -> {
161 | })
162 | .build()
163 | .show();
164 | }
165 |
166 | @OnClick(R.id.increment_offset)
167 | void incrementOffsetAction() {
168 | tweakOffset(1);
169 | }
170 |
171 | @OnClick(R.id.decrement_offset)
172 | void decrementOffsetAction() {
173 | tweakOffset(-1);
174 | }
175 |
176 | //############################################################################################## LISTENER
177 | public interface OnBackgroundChangedListener {
178 | void onDrawBackgroundChanged(boolean draw);
179 |
180 | void onBackgroundColorChanged(int color);
181 |
182 | void onBackgroundOffsetChanged(int offset);
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ramijemli/sample/fragment/ProgressSubFragment.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.sample.fragment;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.ColorStateList;
6 | import android.graphics.Color;
7 | import android.os.Bundle;
8 | import android.util.TypedValue;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.Button;
13 | import android.widget.CheckBox;
14 | import android.widget.RadioGroup;
15 | import android.widget.SeekBar;
16 | import android.widget.TextView;
17 | import android.widget.Toast;
18 |
19 | import com.flask.colorpicker.ColorPickerView;
20 | import com.flask.colorpicker.builder.ColorPickerDialogBuilder;
21 | import com.ramijemli.percentagechartview.renderer.RingModeRenderer;
22 | import com.ramijemli.sample.R;
23 | import com.ramijemli.sample.util.ScreenUtil;
24 |
25 | import androidx.annotation.NonNull;
26 | import androidx.annotation.Nullable;
27 | import androidx.constraintlayout.widget.Group;
28 | import androidx.fragment.app.Fragment;
29 | import butterknife.BindView;
30 | import butterknife.ButterKnife;
31 | import butterknife.OnClick;
32 | import butterknife.Unbinder;
33 |
34 |
35 | public class ProgressSubFragment extends Fragment {
36 |
37 | public static final String BAR_STATE_ARG = "ProgressSubFragment.BAR_STATE_ARG";
38 |
39 | //PROGRESS
40 | @BindView(R.id.progress_value)
41 | SeekBar mProgressValue;
42 | @BindView(R.id.progress_value_label)
43 | TextView mProgressLabel;
44 | @BindView(R.id.animate)
45 | CheckBox mAnimateProgress;
46 |
47 | //PROGRESS COLOR
48 | @BindView(R.id.progress_color)
49 | Button mProgressColor;
50 |
51 | //PROGRESS BAR THICKNESS
52 | @BindView(R.id.prog_thickness_value)
53 | TextView mPgBarThicknessValue;
54 |
55 | //PROGRESS BAR STYLE
56 | @BindView(R.id.prog_bar_style_value)
57 | RadioGroup mPgBarStyle;
58 |
59 | @BindView(R.id.bar_visibility)
60 | Group mBarGroup;
61 |
62 | private OnProgressChangedListener mListener;
63 | private Unbinder unbinder;
64 | private boolean enableBar;
65 |
66 | public ProgressSubFragment() {
67 | }
68 |
69 | public static ProgressSubFragment newInstance() {
70 | return new ProgressSubFragment();
71 | }
72 |
73 | @Override
74 | public void onAttach(Context context) {
75 | super.onAttach(context);
76 | if (context instanceof OnProgressChangedListener) {
77 | mListener = (OnProgressChangedListener) context;
78 | } else {
79 | throw new RuntimeException(context.toString()
80 | + " must implement OnProgressChangedListener");
81 | }
82 | }
83 |
84 | @Override
85 | public void onDetach() {
86 | super.onDetach();
87 | mListener = null;
88 | }
89 |
90 | @Override
91 | public void onCreate(Bundle savedInstanceState) {
92 | super.onCreate(savedInstanceState);
93 | if (getArguments() != null) {
94 | enableBar = getArguments().getBoolean(BAR_STATE_ARG, false);
95 | }
96 | }
97 |
98 | @Override
99 | public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
100 | Bundle savedInstanceState) {
101 | View view = inflater.inflate(R.layout.sub_fragment_progress, container, false);
102 | unbinder = ButterKnife.bind(this, view);
103 | return view;
104 | }
105 |
106 | @Override
107 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
108 | super.onViewCreated(view, savedInstanceState);
109 | setupProgress();
110 | if(enableBar){
111 | mBarGroup.setVisibility(View.VISIBLE);
112 | setupPgBarStyle();
113 | } else {
114 | mBarGroup.setVisibility(View.GONE);
115 | }
116 | }
117 |
118 | @Override
119 | public void onDestroyView() {
120 | mProgressValue.setOnSeekBarChangeListener(null);
121 | mAnimateProgress.setOnCheckedChangeListener(null);
122 | mPgBarStyle.setOnCheckedChangeListener(null);
123 | unbinder.unbind();
124 | unbinder = null;
125 | super.onDestroyView();
126 | }
127 |
128 | //############################################################################################## BEHAVIOR
129 | private void setupProgress() {
130 | mProgressValue.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
131 | @Override
132 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
133 | mProgressLabel.setText(String.valueOf(progress));
134 |
135 | if (mAnimateProgress.isChecked()) return;
136 |
137 | if (mListener != null) {
138 | mListener.onProgressChanged(progress, false);
139 | }
140 | }
141 |
142 | @Override
143 | public void onStartTrackingTouch(SeekBar seekBar) {
144 |
145 | }
146 |
147 | @Override
148 | public void onStopTrackingTouch(SeekBar seekBar) {
149 | if (mAnimateProgress.isChecked()) {
150 | if (mListener != null) {
151 | mListener.onProgressChanged(seekBar.getProgress(), true);
152 | }
153 | }
154 | mProgressLabel.setText(String.valueOf(seekBar.getProgress()));
155 | }
156 | });
157 | }
158 |
159 | private void setupPgBarStyle() {
160 | mPgBarStyle.setOnCheckedChangeListener((group, checkedId) -> {
161 | if (mListener == null) return;
162 | switch (checkedId) {
163 | case R.id.round:
164 | mListener.onProgBarStyleChanged(RingModeRenderer.CAP_ROUND);
165 | break;
166 | case R.id.square:
167 | mListener.onProgBarStyleChanged(RingModeRenderer.CAP_SQUARE);
168 | break;
169 | }
170 | });
171 | }
172 |
173 | private void tweakPgThickness(int amount) {
174 | int value = getTextViewValue(mPgBarThicknessValue);
175 |
176 | int maxValue = (int) ScreenUtil.convertPixelsToDIP(getActivity(), getView().getMeasuredWidth() / 2);
177 | if (value + amount > maxValue) {
178 | value =maxValue;
179 | } else if (value + amount <= 0) {
180 | value = 0;
181 | } else {
182 | value += amount;
183 | }
184 |
185 | mPgBarThicknessValue.setText(value + " dp");
186 | if (mListener != null) {
187 | mListener.onProgBarThicknessChanged(ScreenUtil.convertDIPToPixels(getActivity(), value));
188 | }
189 | }
190 |
191 | private int getTextViewValue(TextView view) {
192 | String value = view.getText().toString();
193 | return Integer.parseInt(value.substring(0, value.length() - 3));
194 | }
195 |
196 | //############################################################################################## ACTIONS
197 | @OnClick(R.id.progress_color)
198 | void progressAction() {
199 | ColorPickerDialogBuilder
200 | .with(getActivity())
201 | .setTitle("Choose progress color")
202 | .initialColor(Color.WHITE)
203 | .wheelType(ColorPickerView.WHEEL_TYPE.FLOWER)
204 | .density(6)
205 | .setPositiveButton("SET", (dialog, selectedColor, allColors) -> {
206 | mProgressColor.setBackgroundTintList(ColorStateList.valueOf(selectedColor));
207 | if (mListener != null) {
208 | mListener.onProgressColorChanged(selectedColor);
209 | }
210 | })
211 | .setNegativeButton("DISMISS", (dialog, which) -> {
212 | })
213 | .build()
214 | .show();
215 | }
216 |
217 | @OnClick(R.id.increment_prog_thickness)
218 | void incrementPgThicknessAction() {
219 | tweakPgThickness(1);
220 | }
221 |
222 | @OnClick(R.id.decrement_prog_thickness)
223 | void decrementPgThicknessAction() {
224 | tweakPgThickness(-1);
225 | }
226 |
227 | //############################################################################################## LISTENER
228 | public interface OnProgressChangedListener {
229 | void onProgressChanged(float progress, boolean animate);
230 |
231 | void onProgressColorChanged(int color);
232 |
233 | default void onProgBarThicknessChanged(int thickness){}
234 |
235 | default void onProgBarStyleChanged(int progressStyle){}
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ramijemli/sample/util/ScreenUtil.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.sample.util;
2 |
3 | import android.content.Context;
4 | import android.content.res.Configuration;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Point;
7 | import android.util.DisplayMetrics;
8 | import android.util.TypedValue;
9 | import android.view.WindowManager;
10 |
11 |
12 | public class ScreenUtil {
13 |
14 | public static int getScreenWidthInDPs(Context context) {
15 | DisplayMetrics dm = new DisplayMetrics();
16 |
17 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
18 | windowManager.getDefaultDisplay().getMetrics(dm);
19 | return Math.round(dm.widthPixels / dm.density);
20 | }
21 |
22 | public static int getScreenHeightInDPs(Context context) {
23 | DisplayMetrics dm = new DisplayMetrics();
24 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
25 | windowManager.getDefaultDisplay().getMetrics(dm);
26 | return Math.round(dm.heightPixels / dm.density);
27 | }
28 |
29 | public static int getScreenWidthInPx(Context context) {
30 | DisplayMetrics dm = new DisplayMetrics();
31 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
32 | windowManager.getDefaultDisplay().getMetrics(dm);
33 | return dm.widthPixels;
34 | }
35 |
36 | public static int getRealScreenWidthInPx(Context context) {
37 | Point size = new Point();
38 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
39 | windowManager.getDefaultDisplay().getRealSize(size);
40 | return size.x;
41 | }
42 |
43 | public static int getScreenHeightInPx(Context context) {
44 | DisplayMetrics dm = new DisplayMetrics();
45 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
46 | windowManager.getDefaultDisplay().getMetrics(dm);
47 | return dm.heightPixels;
48 | }
49 |
50 | public static int getRealScreenHeigthInPx(Context context) {
51 | Point size = new Point();
52 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
53 | windowManager.getDefaultDisplay().getRealSize(size);
54 | return size.y;
55 | }
56 |
57 | /**
58 | * Converts the given device independent pixels (DIP) value into the corresponding pixels
59 | * value for the current screen.
60 | *
61 | * @param context Context instance
62 | * @param dip The DIP value to convert
63 | * @return The pixels value for the current screen of the given DIP value.
64 | */
65 | public static int convertDIPToPixels(Context context, int dip) {
66 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
67 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
68 | }
69 |
70 | /**
71 | * Converts the given device independent pixels (DIP) value into the corresponding pixels
72 | * value for the current screen.
73 | *
74 | * @param context Context instance
75 | * @param dip The DIP value to convert
76 | * @return The pixels value for the current screen of the given DIP value.
77 | */
78 | public static int convertDIPToPixels(Context context, float dip) {
79 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
80 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
81 | }
82 |
83 | /**
84 | * Converts the given pixels value into the corresponding device independent pixels (DIP)
85 | * value for the current screen.
86 | *
87 | * @param context Context instance
88 | * @param pixels The pixels value to convert
89 | * @return The DIP value for the current screen of the given pixels value.
90 | */
91 | public static float convertPixelsToDIP(Context context, int pixels) {
92 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
93 | return pixels / (displayMetrics.densityDpi / 160f);
94 | }
95 |
96 | /**
97 | * Returns the current screen dimensions in device independent pixels (DIP) as a {@link Point} object where
98 | * {@link Point#x} is the screen width and {@link Point#y} is the screen height.
99 | *
100 | * @param context Context instance
101 | * @return The current screen dimensions in DIP.
102 | */
103 | public static Point getScreenDimensionsInDIP(Context context) {
104 | Configuration configuration = context.getResources().getConfiguration();
105 | return new Point(configuration.screenWidthDp, configuration.screenHeightDp);
106 | }
107 |
108 | /**
109 | * @param context Context instance
110 | * @return [true] if the device is in landscape orientation, [false] otherwise.
111 | */
112 | public static boolean isInLandscapeOrientation(Context context) {
113 | Configuration configuration = context.getResources().getConfiguration();
114 | return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE;
115 | }
116 |
117 | /**
118 | * @param context Context instance
119 | * @return [true] if the device has a small screen, [false] otherwise.
120 | */
121 | public static boolean hasSmallScreen(Context context) {
122 | return getScreenSize(context) == Configuration.SCREENLAYOUT_SIZE_SMALL;
123 | }
124 |
125 | /**
126 | * @param context Context instance
127 | * @return [true] if the device has a normal screen, [false] otherwise.
128 | */
129 | public static boolean hasNormalScreen(Context context) {
130 | return getScreenSize(context) == Configuration.SCREENLAYOUT_SIZE_NORMAL;
131 | }
132 |
133 | /**
134 | * @param context Context instance
135 | * @return [true] if the device has a large screen, [false] otherwise.
136 | */
137 | public static boolean hasLargeScreen(Context context) {
138 | return getScreenSize(context) == Configuration.SCREENLAYOUT_SIZE_LARGE;
139 | }
140 |
141 | /**
142 | * @param context Context instance
143 | * @return [true] if the device has an extra large screen, [false] otherwise.
144 | */
145 | public static boolean hasXLargeScreen(Context context) {
146 | return getScreenSize(context) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
147 | }
148 |
149 | /**
150 | * The size of the screen, one of 4 possible values:
151 | *
152 | *
153 | * - http://developer.android.com/reference/android/content/res/Configuration.html#SCREENLAYOUT_SIZE_SMALL
154 | * - http://developer.android.com/reference/android/content/res/Configuration.html#SCREENLAYOUT_SIZE_NORMAL
155 | * - http://developer.android.com/reference/android/content/res/Configuration.html#SCREENLAYOUT_SIZE_LARGE
156 | * - http://developer.android.com/reference/android/content/res/Configuration.html#SCREENLAYOUT_SIZE_XLARGE
157 | *
158 | *
159 | * See http://developer.android.com/reference/android/content/res/Configuration.html#screenLayout for more details.
160 | *
161 | * @param context Context instance
162 | * @return The size of the screen
163 | */
164 | private static int getScreenSize(Context context) {
165 | Configuration configuration = context.getResources().getConfiguration();
166 | return configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
167 | }
168 |
169 |
170 | public static int getStatusBarHeight(Context context) {
171 | int result = 0;
172 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
173 | if (resourceId > 0) {
174 | result = context.getResources().getDimensionPixelSize(resourceId);
175 | }
176 | return result;
177 | }
178 |
179 | public static int getActionBarHeight(Context context) {
180 | final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
181 | new int[]{android.R.attr.actionBarSize});
182 | int result = (int) styledAttributes.getDimension(0, 0);
183 | styledAttributes.recycle();
184 | return result;
185 | }
186 |
187 | public static boolean hasNavBar(Context context) {
188 | int id = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
189 | return id > 0 && context.getResources().getBoolean(id);
190 | }
191 |
192 |
193 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/ramijemli/sample/viewmodel/Showcase.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.sample.viewmodel;
2 |
3 | public class Showcase {
4 | private int color;
5 | private String title;
6 | private String subtitle;
7 |
8 | public Showcase(int color, String title, String subtitle) {
9 | this.color = color;
10 | this.title = title;
11 | this.subtitle = subtitle;
12 | }
13 |
14 | public int getColor() {
15 | return color;
16 | }
17 |
18 | public void setColor(int color) {
19 | this.color = color;
20 | }
21 |
22 | public String getTitle() {
23 | return title;
24 | }
25 |
26 | public void setTitle(String title) {
27 | this.title = title;
28 | }
29 |
30 | public String getSubtitle() {
31 | return subtitle;
32 | }
33 |
34 | public void setSubtitle(String subtitle) {
35 | this.subtitle = subtitle;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/res/color/all_tab_tint_s.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_collapse.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
14 |
17 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_decrement.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_expand.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
15 |
19 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_fill.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
11 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_github.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_increment.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_paint.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_pie.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ico_ring.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/all_ripple_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/all_bg_btn.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/all_bg_mode.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/all_card_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/all_card_bg_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/home_bg_anchor.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/home_bg_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_adaptive_colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
24 |
25 |
42 |
43 |
58 |
59 |
67 |
68 |
69 |
84 |
85 |
100 |
101 |
115 |
116 |
117 |
129 |
130 |
144 |
145 |
159 |
160 |
172 |
173 |
185 |
186 |
198 |
199 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_fill.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
22 |
23 |
33 |
34 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
22 |
23 |
38 |
39 |
53 |
54 |
68 |
69 |
73 |
74 |
75 |
76 |
77 |
78 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_pie.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
22 |
23 |
33 |
34 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_ring.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
24 |
25 |
35 |
36 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_text_formatter.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
12 |
13 |
19 |
20 |
36 |
37 |
48 |
49 |
65 |
66 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/custom_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_dev.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
20 |
21 |
35 |
36 |
50 |
51 |
65 |
66 |
80 |
81 |
98 |
99 |
113 |
114 |
131 |
132 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
30 |
31 |
48 |
49 |
66 |
67 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_interpolator.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sub_fragment_background.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
14 |
15 |
23 |
24 |
27 |
28 |
29 |
41 |
42 |
55 |
56 |
71 |
72 |
73 |
85 |
86 |
99 |
100 |
113 |
114 |
115 |
127 |
128 |
138 |
139 |
151 |
152 |
162 |
163 |
177 |
178 |
183 |
184 |
190 |
191 |
192 |
193 |
194 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sub_fragment_background_bar.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
14 |
15 |
23 |
24 |
27 |
28 |
29 |
41 |
42 |
55 |
56 |
69 |
70 |
71 |
83 |
84 |
97 |
98 |
111 |
112 |
113 |
125 |
126 |
136 |
137 |
149 |
150 |
160 |
161 |
175 |
176 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/sub_fragment_behavior.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
14 |
15 |
23 |
24 |
27 |
28 |
29 |
41 |
42 |
53 |
54 |
63 |
64 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
95 |
96 |
110 |
111 |
124 |
125 |
126 |
138 |
139 |
149 |
150 |
162 |
163 |
173 |
174 |
186 |
187 |
188 |
200 |
201 |
212 |
213 |
225 |
226 |
232 |
233 |
234 |
235 |
236 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000
4 | #000
5 | #F44336
6 | #263238
7 |
8 | #03A9F4
9 | #FFC107
10 | #00BCD4
11 | #9C27B0
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Percentage Chart View
3 |
4 | PERCENTAGE CHART VIEW
5 | v0.3.0 library showcase app
6 |
7 |
8 | - @color/colorAccent
9 | - @color/colorAccent
10 | - @color/colorAccent
11 | - @color/colorCyan
12 | - @color/colorYellow
13 | - @color/colorBlue
14 |
15 |
16 |
17 | - PIE MODE PLAYGROUND
18 | - RING MODE PLAYGROUND
19 | - FILL MODE PLAYGROUND
20 | - ADAPTIVE COLOR PROVIDER SHOWCASE
21 | - GRADIENT COLORS SHOWCASE
22 | - TEXT FORMATTER SHOWCASE
23 |
24 |
25 |
26 | - Explore pie mode with all its related attributes
27 | - Explore ring mode with all its related attributes
28 | - Explore fill mode with all its related attributes
29 | - See the adaptive color provider in action
30 | - Check the progress gradient colors in action
31 | - Check the text formatter in action
32 | - Check how SpringAnimation differs from the regular animations
33 |
34 |
35 | ORIENTATION
36 | Clockwise
37 | Counter clockwise
38 | START ANGLE
39 | PROGRESS
40 | Use animation
41 | ANIM DURATION
42 | 1000 ms by default
43 | ANIM INTERPOLATOR
44 | LinearInterpolator by default
45 | TEXT COLOR
46 | WHITE by default
47 | TEXT SIZE
48 | 12 sp default
49 | TEXT FONT
50 | TEXT FONT STYLE
51 | TEXT SHADOW
52 | Use shadow
53 | COLOR
54 | RADIUS
55 | DISTANCE X
56 | DISTANCE Y
57 | DRAW BACKGROUND
58 | By default, true for pie mode and false for ring mode
59 | True
60 | BACKGROUND COLOR
61 | BLACK by default
62 | BACKGROUND OFFSET
63 | Applicable only in pie mode and 0 by default
64 | PROGRESS COLOR
65 | ACCENT color by default
66 | PROGRESS BAR THICKNESS
67 | Applicable only in ring mode and 16 dp by default
68 | PROGRESS BAR STYLE
69 | ROUND
70 | SQUARE
71 | DRAW BG BAR
72 | True by default
73 | True
74 | BG BAR COLOR
75 | BLACK by default
76 | BG BAR THICKNESS
77 | Applicable only in ring mode and 16dp by default
78 | ADAPTIVE COLOR PROVIDER
79 | We can get colors to change according to progress value. Here we have 4 colors we can pick and use that are passed to the custom view by providing an AdaptiveColorProvider Class.
80 | Use AdaptiveColorProvider
81 | ADAPTIVE TEXT COLOR
82 | When a provider is used. We can have a progress based adaptive color for the text too. By default, it\'s set to 50% lighter than the progress color. We can tweak the percentage by applying the adaptive text ratio value and the adaptive mode to get a darker/lighter color.
83 | Use adaptive text color
84 | RATIO
85 | TEXT MODE
86 | Darker
87 | Lighter
88 | ADAPTIVE BACKGROUND COLOR
89 | When a provider is used. We can have a progress based adaptive color for the background too. By default, it\'s set to 50% darker than the progress color. We can tweak the percentage by applying the adaptive background ratio value and the adaptive mode to get a darker/lighter color.
90 | Use adaptive background color
91 | RATIO
92 | BG MODE
93 | Darker
94 | Lighter
95 | ADAPTIVE BACKGROUND BAR COLOR
96 | When a provider is used. We can have a progress based adaptive color for the background bar too. By default, it\'s set to 50% darker than the progress color. We can tweak the percentage by applying the adaptive background ratio value and the adaptive mode to get a darker/lighter color.
97 | Use adaptive bg bar color
98 | RATIO
99 | BG BAR MODE
100 | Darker
101 | Lighter
102 | GitHub URL
103 | https://github.com/RamiJ3mli/PercentageChartView
104 | Developed by Rami Jemli
105 |
106 |
107 | Hello blank fragment
108 | GRADIENT TYPE
109 | Linear
110 | Radial
111 | Sweep
112 | LINEAR GRADIENT ANGLE
113 |
114 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/art/angle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/angle.png
--------------------------------------------------------------------------------
/art/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/cover.png
--------------------------------------------------------------------------------
/art/google-play-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/google-play-badge.png
--------------------------------------------------------------------------------
/art/showcase_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_1.gif
--------------------------------------------------------------------------------
/art/showcase_10.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_10.gif
--------------------------------------------------------------------------------
/art/showcase_11.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_11.gif
--------------------------------------------------------------------------------
/art/showcase_12.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_12.gif
--------------------------------------------------------------------------------
/art/showcase_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_2.gif
--------------------------------------------------------------------------------
/art/showcase_3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_3.gif
--------------------------------------------------------------------------------
/art/showcase_4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_4.gif
--------------------------------------------------------------------------------
/art/showcase_5.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_5.gif
--------------------------------------------------------------------------------
/art/showcase_6.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_6.gif
--------------------------------------------------------------------------------
/art/showcase_7.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_7.gif
--------------------------------------------------------------------------------
/art/showcase_8.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_8.gif
--------------------------------------------------------------------------------
/art/showcase_9.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/art/showcase_9.gif
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 |
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.4.0'
11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
13 | }
14 | }
15 |
16 | allprojects {
17 | repositories {
18 | google()
19 | jcenter()
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamiJ3mli/PercentageChartView/80df5df39b7d0d2ff658487dcf90d380892b270f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Apr 20 12:48:53 GMT+01:00 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/percentagechartview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/percentagechartview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.jfrog.bintray'
3 | apply plugin: 'com.github.dcendents.android-maven'
4 |
5 | ext {
6 | bintrayRepo = "PercentageChartView"
7 | bintrayName = "com.ramijemli.percentagechartview"
8 | libraryName = "percentagechartview"
9 |
10 | publishedGroupId = 'com.ramijemli.percentagechartview'
11 | artifact = 'percentagechartview'
12 | libraryVersion = '0.3.1'
13 |
14 | libraryDescription = 'An Android percentage chart custom view that displays the progress of any single given task or information.'
15 | siteUrl = 'https://github.com/RamiJ3mli/PercentageChartView'
16 | gitUrl = 'https://github.com/RamiJ3mli/PercentageChartView.git'
17 | developerId = 'ramijemli'
18 | developerName = 'Rami Jemli'
19 | developerEmail = 'jemli.idea@gmail.com'
20 | licenseName = 'The Apache Software Licence, Version 2.0'
21 | licenseUrl = 'https://www.apache.org/licenses/LICENSE-2.0'
22 | allLicenses = ["Apache-2.0"]
23 |
24 | }
25 |
26 | android {
27 | compileSdkVersion 28
28 |
29 | defaultConfig {
30 | minSdkVersion 16
31 | targetSdkVersion 28
32 | versionCode 7
33 | versionName "0.3.1"
34 |
35 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
36 | }
37 |
38 | buildTypes {
39 | release {
40 | minifyEnabled false
41 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
42 | }
43 | }
44 |
45 | compileOptions {
46 | sourceCompatibility JavaVersion.VERSION_1_8
47 | targetCompatibility JavaVersion.VERSION_1_8
48 | }
49 | }
50 |
51 | dependencies {
52 | implementation fileTree(dir: 'libs', include: ['*.jar'])
53 | implementation 'androidx.appcompat:appcompat:1.0.2'
54 | }
55 |
56 | if (rootProject.file('local.properties').exists()) {
57 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
58 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
59 | }
60 |
--------------------------------------------------------------------------------
/percentagechartview/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/IPercentageChartView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview;
18 |
19 | import android.content.Context;
20 |
21 | public interface IPercentageChartView {
22 |
23 | Context getViewContext();
24 |
25 | void postInvalidate();
26 |
27 | void postInvalidateOnAnimation();
28 |
29 | boolean isInEditMode();
30 |
31 | int getWidth();
32 |
33 | int getHeight();
34 |
35 | void onProgressUpdated(float progress);
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/annotation/ChartMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.annotation;
18 |
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 |
22 | import androidx.annotation.IntDef;
23 |
24 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.MODE_FILL;
25 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.MODE_PIE;
26 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.MODE_RING;
27 |
28 | @Retention(RetentionPolicy.SOURCE)
29 | @IntDef({MODE_PIE, MODE_RING, MODE_FILL})
30 | public @interface ChartMode {
31 | }
32 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/annotation/GradientTypes.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.annotation;
18 |
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 |
22 | import androidx.annotation.IntDef;
23 |
24 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.GRADIENT_LINEAR;
25 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.GRADIENT_RADIAL;
26 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.GRADIENT_SWEEP;
27 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.INVALID_GRADIENT;
28 |
29 | @Retention(RetentionPolicy.SOURCE)
30 | @IntDef({INVALID_GRADIENT, GRADIENT_LINEAR, GRADIENT_RADIAL, GRADIENT_SWEEP})
31 | public @interface GradientTypes {
32 | }
33 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/annotation/ProgressBarStyle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.annotation;
18 |
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 |
22 | import androidx.annotation.IntDef;
23 |
24 | import static com.ramijemli.percentagechartview.renderer.RingModeRenderer.CAP_ROUND;
25 | import static com.ramijemli.percentagechartview.renderer.RingModeRenderer.CAP_SQUARE;
26 |
27 | @Retention(RetentionPolicy.SOURCE)
28 | @IntDef({CAP_ROUND, CAP_SQUARE})
29 | public @interface ProgressBarStyle {
30 | }
31 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/annotation/ProgressOrientation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.annotation;
18 |
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.RetentionPolicy;
21 |
22 | import androidx.annotation.IntDef;
23 |
24 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.INVALID_ORIENTATION;
25 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.ORIENTATION_CLOCKWISE;
26 | import static com.ramijemli.percentagechartview.renderer.BaseModeRenderer.ORIENTATION_COUNTERCLOCKWISE;
27 |
28 | @Retention(RetentionPolicy.SOURCE)
29 | @IntDef({INVALID_ORIENTATION, ORIENTATION_CLOCKWISE, ORIENTATION_COUNTERCLOCKWISE})
30 | public @interface ProgressOrientation {
31 | }
32 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/annotation/TextStyle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.annotation;
18 |
19 | import android.graphics.Typeface;
20 |
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 |
24 | import androidx.annotation.IntDef;
25 |
26 | @Retention(RetentionPolicy.SOURCE)
27 | @IntDef({Typeface.NORMAL, Typeface.BOLD, Typeface.ITALIC, Typeface.BOLD_ITALIC})
28 | public @interface TextStyle {
29 | }
30 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/callback/AdaptiveColorProvider.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.percentagechartview.callback;
2 |
3 | public interface AdaptiveColorProvider {
4 |
5 | default int provideProgressColor(float progress) {
6 | return -1;
7 | }
8 |
9 | default int provideBackgroundColor(float progress) {
10 | return -1;
11 | }
12 |
13 | default int provideTextColor(float progress) {
14 | return -1;
15 | }
16 |
17 | default int provideBackgroundBarColor(float progress) {
18 | return -1;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/callback/OnProgressChangeListener.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.percentagechartview.callback;
2 |
3 | public interface OnProgressChangeListener {
4 |
5 | void onProgressChanged(float progress);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/callback/ProgressTextFormatter.java:
--------------------------------------------------------------------------------
1 | package com.ramijemli.percentagechartview.callback;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public interface ProgressTextFormatter {
6 |
7 | @NonNull
8 | CharSequence provideFormattedText(float progress);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/renderer/FillModeRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.renderer;
18 |
19 | import android.content.res.TypedArray;
20 | import android.graphics.Canvas;
21 | import android.graphics.LinearGradient;
22 | import android.graphics.Matrix;
23 | import android.graphics.RadialGradient;
24 | import android.graphics.RectF;
25 | import android.graphics.Shader;
26 |
27 | import androidx.annotation.Nullable;
28 |
29 | import com.ramijemli.percentagechartview.IPercentageChartView;
30 | import com.ramijemli.percentagechartview.callback.AdaptiveColorProvider;
31 |
32 | public class FillModeRenderer extends BaseModeRenderer implements OffsetEnabledMode {
33 |
34 | private float mDirectionAngle;
35 | private float mBgSweepAngle;
36 | private float mRadius;
37 |
38 | public FillModeRenderer(IPercentageChartView view) {
39 | super(view);
40 | setup();
41 | }
42 |
43 | public FillModeRenderer(IPercentageChartView view, TypedArray attrs) {
44 | super(view, attrs);
45 | setup();
46 | }
47 |
48 | @Override
49 | void setup() {
50 | super.setup();
51 | this.mDirectionAngle = mStartAngle;
52 | }
53 |
54 | @Override
55 | public void measure(int w, int h, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
56 | int centerX = w / 2;
57 | int centerY = h / 2;
58 | mRadius = (float) Math.min(w, h) / 2;
59 |
60 | mCircleBounds.set(centerX - mRadius,
61 | centerY - mRadius,
62 | centerX + mRadius,
63 | centerY + mRadius);
64 | measureBackgroundBounds();
65 | updateDrawingAngles();
66 | setupGradientColors(mCircleBounds);
67 | updateText();
68 | }
69 |
70 | private void measureBackgroundBounds() {
71 | mBackgroundBounds.set(mCircleBounds.left + mBackgroundOffset,
72 | mCircleBounds.top + mBackgroundOffset,
73 | mCircleBounds.right - mBackgroundOffset,
74 | mCircleBounds.bottom - mBackgroundOffset);
75 | }
76 |
77 | @Override
78 | public void draw(Canvas canvas) {
79 | //BACKGROUND
80 | if (mDrawBackground) {
81 | canvas.drawArc(mBackgroundBounds, mStartAngle, mBgSweepAngle, false, mBackgroundPaint);
82 | }
83 |
84 | //FOREGROUND
85 | canvas.drawArc(mCircleBounds, mStartAngle, mSweepAngle, false, mProgressPaint);
86 |
87 | //TEXT
88 | drawText(canvas);
89 | }
90 |
91 | @Override
92 | public void setAdaptiveColorProvider(@Nullable AdaptiveColorProvider adaptiveColorProvider) {
93 | if (adaptiveColorProvider == null) {
94 | mProgressColorAnimator = mBackgroundColorAnimator = mTextColorAnimator = null;
95 | this.mAdaptiveColorProvider = null;
96 | mTextPaint.setColor(mTextColor);
97 | mBackgroundPaint.setColor(mBackgroundColor);
98 | mProgressPaint.setColor(mProgressColor);
99 | mView.postInvalidate();
100 | return;
101 | }
102 |
103 | this.mAdaptiveColorProvider = adaptiveColorProvider;
104 |
105 | setupColorAnimations();
106 | updateProvidedColors(mProgress);
107 | mView.postInvalidate();
108 | }
109 |
110 | @Override
111 | void setupGradientColors(RectF bounds) {
112 | if (mGradientType == -1 || mGradientType == GRADIENT_SWEEP) return;
113 |
114 | switch (mGradientType) {
115 | default:
116 | case GRADIENT_LINEAR:
117 | mGradientShader = new LinearGradient(bounds.centerX(), bounds.top, bounds.centerX(), bounds.bottom, mGradientColors, mGradientDistributions, Shader.TileMode.CLAMP);
118 | updateGradientAngle(mGradientAngle);
119 | break;
120 |
121 | case GRADIENT_RADIAL:
122 | mGradientShader = new RadialGradient(bounds.centerX(), bounds.centerY(), bounds.bottom - bounds.centerY(), mGradientColors, mGradientDistributions, Shader.TileMode.MIRROR);
123 | break;
124 | }
125 |
126 | mProgressPaint.setShader(mGradientShader);
127 | }
128 |
129 | @Override
130 | void updateDrawingAngles() {
131 | float height = mRadius - mProgress * (mRadius * 2) / DEFAULT_MAX;
132 | double radiusPow = Math.pow(mRadius, 2);
133 | double heightPow = Math.pow(height, 2);
134 |
135 | mSweepAngle = (height == 0) ? 180 : (float) Math.toDegrees(Math.acos((heightPow + radiusPow - Math.pow(Math.sqrt(radiusPow - heightPow), 2)) / (2 * height * mRadius))) * 2;
136 | mStartAngle = mDirectionAngle - (mSweepAngle / 2);
137 | mBgSweepAngle = (mBackgroundOffset > 0) ? 360 : mSweepAngle - 360;
138 | }
139 |
140 | @Override
141 | void updateGradientAngle(float angle) {
142 | if (mGradientType == -1 || mGradientType == GRADIENT_RADIAL) return;
143 | Matrix matrix = new Matrix();
144 | matrix.postRotate(angle, mCircleBounds.centerX(), mCircleBounds.centerY());
145 | mGradientShader.setLocalMatrix(matrix);
146 | }
147 |
148 | @Override
149 | public float getStartAngle() {
150 | return mDirectionAngle;
151 | }
152 |
153 | @Override
154 | public void setStartAngle(float angle) {
155 | if (this.mDirectionAngle == angle) return;
156 | this.mDirectionAngle = angle;
157 | updateDrawingAngles();
158 | }
159 |
160 | //BACKGROUND OFFSET
161 | public int getBackgroundOffset() {
162 | return mBackgroundOffset;
163 | }
164 |
165 | public void setBackgroundOffset(int backgroundOffset) {
166 | if (!mDrawBackground || this.mBackgroundOffset == backgroundOffset)
167 | return;
168 | this.mBackgroundOffset = backgroundOffset;
169 | measureBackgroundBounds();
170 | updateDrawingAngles();
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/renderer/OffsetEnabledMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.renderer;
18 |
19 | public interface OffsetEnabledMode {
20 |
21 | int getBackgroundOffset();
22 |
23 | void setBackgroundOffset(int backgroundOffset);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/renderer/OrientationBasedMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.renderer;
18 |
19 | public interface OrientationBasedMode {
20 |
21 | void setOrientation(int orientation);
22 |
23 | int getOrientation();
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/java/com/ramijemli/percentagechartview/renderer/PieModeRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Rami Jemli
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ramijemli.percentagechartview.renderer;
18 |
19 |
20 | import android.content.res.TypedArray;
21 | import android.graphics.Canvas;
22 | import android.graphics.LinearGradient;
23 | import android.graphics.Matrix;
24 | import android.graphics.RadialGradient;
25 | import android.graphics.RectF;
26 | import android.graphics.Shader;
27 | import android.graphics.SweepGradient;
28 |
29 | import androidx.annotation.Nullable;
30 |
31 | import com.ramijemli.percentagechartview.IPercentageChartView;
32 | import com.ramijemli.percentagechartview.callback.AdaptiveColorProvider;
33 |
34 |
35 | public class PieModeRenderer extends BaseModeRenderer implements OrientationBasedMode, OffsetEnabledMode {
36 |
37 | private float mBgStartAngle;
38 | private float mBgSweepAngle;
39 |
40 | public PieModeRenderer(IPercentageChartView view) {
41 | super(view);
42 | setup();
43 | }
44 |
45 | public PieModeRenderer(IPercentageChartView view, TypedArray attrs) {
46 | super(view, attrs);
47 | setup();
48 | }
49 |
50 | @Override
51 | void setup() {
52 | super.setup();
53 | updateDrawingAngles();
54 | }
55 |
56 | @Override
57 | public void measure(int w, int h, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
58 | float centerX = w * 0.5f;
59 | float centerY = h * 0.5f;
60 | float radius = Math.min(w, h) * 0.5f;
61 |
62 | mCircleBounds.set(centerX - radius,
63 | centerY - radius,
64 | centerX + radius,
65 | centerY + radius);
66 | measureBackgroundBounds();
67 | setupGradientColors(mCircleBounds);
68 | updateText();
69 | }
70 |
71 | private void measureBackgroundBounds() {
72 | mBackgroundBounds.set(mCircleBounds.left + mBackgroundOffset,
73 | mCircleBounds.top + mBackgroundOffset,
74 | mCircleBounds.right - mBackgroundOffset,
75 | mCircleBounds.bottom - mBackgroundOffset);
76 | }
77 |
78 | @Override
79 | public void draw(Canvas canvas) {
80 | if (mGradientType == GRADIENT_SWEEP && mView.isInEditMode()) {
81 | // TO GET THE RIGHT DRAWING START ANGLE FOR SWEEP GRADIENT'S COLORS IN PREVIEW MODE
82 | canvas.save();
83 | canvas.rotate(mStartAngle, mCircleBounds.centerX(), mCircleBounds.centerY());
84 | }
85 |
86 | //FOREGROUND
87 | canvas.drawArc(mCircleBounds, mStartAngle, mSweepAngle, true, mProgressPaint);
88 |
89 | //BACKGROUND
90 | if (mDrawBackground) {
91 | canvas.drawArc(mBackgroundBounds, mBgStartAngle, mBgSweepAngle, true, mBackgroundPaint);
92 | }
93 |
94 | if (mGradientType == GRADIENT_SWEEP && mView.isInEditMode()) {
95 | // TO GET THE RIGHT DRAWING START ANGLE FOR SWEEP GRADIENT'S COLORS IN PREVIEW MODE
96 | canvas.restore();
97 | }
98 |
99 | //TEXT
100 | drawText(canvas);
101 | }
102 |
103 | @Override
104 | public void setAdaptiveColorProvider(@Nullable AdaptiveColorProvider adaptiveColorProvider) {
105 | if (adaptiveColorProvider == null) {
106 | mProgressColorAnimator = mBackgroundColorAnimator = mTextColorAnimator = null;
107 | mAdaptiveColorProvider = null;
108 | mTextPaint.setColor(mTextColor);
109 | mBackgroundPaint.setColor(mBackgroundColor);
110 | mProgressPaint.setColor(mProgressColor);
111 | mView.postInvalidate();
112 | return;
113 | }
114 |
115 | this.mAdaptiveColorProvider = adaptiveColorProvider;
116 |
117 | setupColorAnimations();
118 | updateProvidedColors(mProgress);
119 | mView.postInvalidate();
120 | }
121 |
122 | @Override
123 | void setupGradientColors(RectF bounds) {
124 | if (mGradientType == -1 && bounds.height() == 0) return;
125 |
126 | switch (mGradientType) {
127 | default:
128 | case GRADIENT_LINEAR:
129 | mGradientShader = new LinearGradient(bounds.centerX(), bounds.top, bounds.centerX(), bounds.bottom, mGradientColors, mGradientDistributions, Shader.TileMode.CLAMP);
130 | updateGradientAngle(mGradientAngle);
131 | break;
132 |
133 | case GRADIENT_RADIAL:
134 | mGradientShader = new RadialGradient(bounds.centerX(), bounds.centerY(), bounds.bottom - bounds.centerY(), mGradientColors, mGradientDistributions, Shader.TileMode.MIRROR);
135 | break;
136 |
137 | case GRADIENT_SWEEP:
138 | mGradientShader = new SweepGradient(bounds.centerX(), bounds.centerY(), mGradientColors, mGradientDistributions);
139 |
140 | if (!mView.isInEditMode()) {
141 | // THIS BREAKS SWEEP GRADIENT'S PREVIEW MODE
142 | updateGradientAngle(mStartAngle);
143 | }
144 | break;
145 | }
146 |
147 | mProgressPaint.setShader(mGradientShader);
148 | }
149 |
150 | @Override
151 | void updateDrawingAngles() {
152 | switch (orientation) {
153 | case ORIENTATION_COUNTERCLOCKWISE:
154 | mSweepAngle = -(mProgress / DEFAULT_MAX * 360);
155 | mBgStartAngle = mStartAngle;
156 | mBgSweepAngle = 360 + mSweepAngle;
157 | break;
158 |
159 | default:
160 | case ORIENTATION_CLOCKWISE:
161 | mSweepAngle = mProgress / DEFAULT_MAX * 360;
162 | mBgStartAngle = mStartAngle + mSweepAngle;
163 | mBgSweepAngle = 360 - mSweepAngle;
164 | break;
165 | }
166 | }
167 |
168 | @Override
169 | void updateGradientAngle(float angle) {
170 | if (mGradientType == -1 || mGradientType == GRADIENT_RADIAL) return;
171 | Matrix matrix = new Matrix();
172 | matrix.postRotate(angle, mCircleBounds.centerX(), mCircleBounds.centerY());
173 | mGradientShader.setLocalMatrix(matrix);
174 | }
175 |
176 | public int getOrientation() {
177 | return orientation;
178 | }
179 |
180 | public void setOrientation(int orientation) {
181 | if (this.orientation == orientation) return;
182 | this.orientation = orientation;
183 | updateDrawingAngles();
184 | }
185 |
186 | @Override
187 | public void setStartAngle(float startAngle) {
188 | if (this.mStartAngle == startAngle) return;
189 | this.mStartAngle = startAngle;
190 | updateDrawingAngles();
191 | if (mGradientType == GRADIENT_SWEEP) {
192 | updateGradientAngle(startAngle);
193 | }
194 | }
195 |
196 | //BACKGROUND OFFSET
197 | public int getBackgroundOffset() {
198 | return mBackgroundOffset;
199 | }
200 |
201 | public void setBackgroundOffset(int backgroundOffset) {
202 | if (!mDrawBackground || this.mBackgroundOffset == backgroundOffset)
203 | return;
204 | this.mBackgroundOffset = backgroundOffset;
205 | measureBackgroundBounds();
206 | }
207 |
208 | }
209 |
--------------------------------------------------------------------------------
/percentagechartview/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':percentagechartview'
2 |
--------------------------------------------------------------------------------